mirror of
https://github.com/friendica/friendica
synced 2024-12-22 22:40:16 +00:00
Merge branch 'master' into develop
This commit is contained in:
commit
b9ab613777
164 changed files with 30233 additions and 26266 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -6,7 +6,6 @@ favicon.*
|
||||||
*.out
|
*.out
|
||||||
*.version*
|
*.version*
|
||||||
home.html
|
home.html
|
||||||
|
|
||||||
*~
|
*~
|
||||||
robots.txt
|
robots.txt
|
||||||
|
|
||||||
|
@ -74,3 +73,6 @@ venv/
|
||||||
|
|
||||||
#ignore filesystem storage default path
|
#ignore filesystem storage default path
|
||||||
/storage
|
/storage
|
||||||
|
|
||||||
|
#Ignore log folder
|
||||||
|
/log
|
||||||
|
|
42
CHANGELOG
42
CHANGELOG
|
@ -1,17 +1,20 @@
|
||||||
Version 2019.06 (UNRELEASED) (2019-06-?)
|
Version 2019.06 (2019-06-23)
|
||||||
Friendica Core:
|
Friendica Core:
|
||||||
Update to the tranlation (CS, DE, ET, PL, PT-BR, SV) [translation teams]
|
Update to the tranlation (CS, DE, EN-GB, EN-US, ET, FR, IT, PL, PT-BR, SV) [translation teams]
|
||||||
Update to the documentation [nupplaphil, realkinetix]
|
Update to the documentation [nupplaphil, realkinetix, MrPetovan]
|
||||||
Update to the themes (frio, vier) [BinkaDroid, MrPetovan, tobiasd]
|
Update to the themes (frio, vier) [BinkaDroid, MrPetovan, tobiasd]
|
||||||
Enhancements to the API [annando, MrPetovan]
|
Enhancements to the API [annando, MrPetovan]
|
||||||
Enhancements to the way reshares are handled [annando]
|
Enhancements to the way reshares are handled [annando]
|
||||||
Enhancements to the redis configuration [nupplaphil]
|
Enhancements to the redis configuration [nupplaphil]
|
||||||
Enhancements to the federation stats display in the admin panel [tobiasd]
|
Enhancements to the federation stats display in the admin panel [tobiasd]
|
||||||
Enhancements to the processing of changed storage engine [MrPetovan]
|
Enhancements to the processing of changed storage engine [MrPetovan]
|
||||||
|
Enhancements to ActivityPub support [annando, MrPetovan]
|
||||||
|
Enhancements to code security [MrPetovan]
|
||||||
|
Enhancements to delivery counter [annando]
|
||||||
Fixed the notification order [JeroenED]
|
Fixed the notification order [JeroenED]
|
||||||
Fixed the timezone of Friendica logs [nupplaphil]
|
Fixed the timezone of Friendica logs [nupplaphil]
|
||||||
Fixed tag completion painfully slow [AlfredSK]
|
Fixed tag completion painfully slow [AlfredSK]
|
||||||
Fixed a regression in notifications [MrPetovan]
|
Fixed a regression in notifications [MrPetovan, annando]
|
||||||
Fixed an issue with smilies and code blocks [MrPetovan]
|
Fixed an issue with smilies and code blocks [MrPetovan]
|
||||||
Fixed an AP issue with unavailable local profiles [MrPetovan]
|
Fixed an AP issue with unavailable local profiles [MrPetovan]
|
||||||
Fixed an issue with the File to Folder feature [MrPetovan]
|
Fixed an issue with the File to Folder feature [MrPetovan]
|
||||||
|
@ -20,35 +23,56 @@ Version 2019.06 (UNRELEASED) (2019-06-?)
|
||||||
Fixed an issue occuring when the BasePath was not set [tobiasd]
|
Fixed an issue occuring when the BasePath was not set [tobiasd]
|
||||||
Fixed an issue with additionally opened Sessions [MrPetovan]
|
Fixed an issue with additionally opened Sessions [MrPetovan]
|
||||||
Fixed an issue with legacy loglevel mapping [nupplaphil]
|
Fixed an issue with legacy loglevel mapping [nupplaphil]
|
||||||
|
Fixed contact suggestions [annando]
|
||||||
|
Fixed an issue with frio hovercard [nupplaphil]
|
||||||
|
Fixed event interaction federation [annando]
|
||||||
|
Fixed remote image permission [deantownsley]
|
||||||
General Code cleaning and restructuring [annando, nupplaphil, tobiasd]
|
General Code cleaning and restructuring [annando, nupplaphil, tobiasd]
|
||||||
Added frio color scheme sharing [JeroenED]
|
Added frio color scheme sharing [JeroenED]
|
||||||
Added syslog and stream Logger [nupplaphil]
|
Added syslog and stream Logger [nupplaphil]
|
||||||
Added storage move cronjob [MrPetovan]
|
Added storage move cronjob [MrPetovan]
|
||||||
Added collapsible panel for connector permission fields [MrPetovan]
|
Added collapsible panel for connector permission fields [MrPetovan]
|
||||||
Added rule-based router [MrPetovan]
|
Added rule-based router [MrPetovan]
|
||||||
Added Estinian translation [Rain Hawk]
|
Added Estonian translation [Rain Hawk]
|
||||||
Added APCu caching [nupplaphil]
|
Added APCu caching [nupplaphil]
|
||||||
Added BlockServer command to the Friendica console [nupplaphil]
|
Added BlockServer command to the Friendica console [nupplaphil]
|
||||||
|
Added reshare count [annando]
|
||||||
|
Added rule-based router [MrPetovan, nupplaphil]
|
||||||
|
Added themed error pages with mascot [MrPetovan, lostinlight]
|
||||||
|
Added contact relationship filter [MrPetovan]
|
||||||
Removed the old queue mechanism (deferred workers are now used) [annando]
|
Removed the old queue mechanism (deferred workers are now used) [annando]
|
||||||
Removed BasePath and Hostname settings from the admin panel [nupplaphil]
|
Removed BasePath and Hostname settings from the admin panel [nupplaphil]
|
||||||
|
Remove support for defunct F-Droid Friendica app [MrPetovan]
|
||||||
|
|
||||||
Friendica Addons:
|
Friendica Addons:
|
||||||
Update to the tranlation (ET, SV, ZH_CN) [translation teams]
|
Update to the tranlation (ET, SV, ZH_CN) [translation teams]
|
||||||
botdetection:
|
botdetection:
|
||||||
Added a new addon for preventing access by bots [nupplaphil]
|
Added a new addon for preventing access by bots [nupplaphil, annando]
|
||||||
buffer:
|
buffer:
|
||||||
Traces of Google+ were removed [annando]
|
Traces of Google+ were removed [annando]
|
||||||
curweather:
|
curweather:
|
||||||
Fixed a problem with the display of the correct temperature unit [tobiasd]
|
Fixed a problem with the display of the correct temperature unit [tobiasd]
|
||||||
fromgplus:
|
fromgplus:
|
||||||
Deprecated the addon as Google+ was closed [tobiasd]
|
Deprecated the addon as Google+ was closed [tobiasd]
|
||||||
|
fortunate:
|
||||||
|
Deprecated addon for incompatibility with latest Friendica version [MrPetovan]
|
||||||
phpmailer:
|
phpmailer:
|
||||||
Added a new addon to use external SMTP for email [M-arcus]
|
Added a new addon to use external SMTP for email [M-arcus, kecalcze, MrPetovan]
|
||||||
|
pledgie:
|
||||||
|
Deprecated addon as service was discontinued [M-arcus]
|
||||||
|
xmpp:
|
||||||
|
Marked addon as unsupported because of various incompatibilities with themes [MrPetovan]
|
||||||
|
|
||||||
Closed Issues:
|
Closed Issues:
|
||||||
5011, 5047, 5850, 6303, 6319, 6478, 6319, 6720, 6815, 6864, 6879,
|
1012, 2209, 2528, 3309, 3717, 3816, 3869, 4453, 4999, 5011, 5047, 5276, 5850, 5983, 6303, 6319, 6379, 6410, 6477,
|
||||||
6903, 6921, 6927, 6936, 6941, 6943, 6947, 6948, 6952
|
6478, 6720, 6799, 6813, 6819, 6861, 6864, 6879, 6903, 6916, 6917, 6918, 6921, 6927, 6929, 6936, 6938, 6941, 6943,
|
||||||
|
6947, 6948, 6950, 6952, 6983, 6999, 7023, 7036, 7047, 7106, 7112, 7119, 7128, 7130, 7131, 7141, 7142, 7150, 7171,
|
||||||
|
7183, 7196, 7209, 7223, 7226, 7240, 7241, 7249, 7264, 7269, 7271, 7275, 7300, 7303
|
||||||
|
|
||||||
|
Version 2019.04 (2019-04-28)
|
||||||
|
Friendica Core:
|
||||||
|
Fixed a privacy problem with postings accessed by feed [MrPetovan]
|
||||||
|
|
||||||
Version 2019.03 (2019-03-22)
|
Version 2019.03 (2019-03-22)
|
||||||
Friendica Core:
|
Friendica Core:
|
||||||
Update to the translation (CS, DE, EN-GB, EN-US, ES, FR, IT, PL, SV, ZH-CN) [translation teams]
|
Update to the translation (CS, DE, EN-GB, EN-US, ES, FR, IT, PL, SV, ZH-CN) [translation teams]
|
||||||
|
|
11
CREDITS.txt
11
CREDITS.txt
|
@ -1,3 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
23n
|
23n
|
||||||
Abinoam P. Marques Jr.
|
Abinoam P. Marques Jr.
|
||||||
Abraham Pérez Hernández
|
Abraham Pérez Hernández
|
||||||
|
@ -26,6 +28,7 @@ Andy Hee
|
||||||
Angristan
|
Angristan
|
||||||
Anthronaut
|
Anthronaut
|
||||||
Arian - Cazare Muncitori
|
Arian - Cazare Muncitori
|
||||||
|
Asher Pen
|
||||||
Athalbert
|
Athalbert
|
||||||
aweiher
|
aweiher
|
||||||
axelt
|
axelt
|
||||||
|
@ -37,6 +40,8 @@ Beluga
|
||||||
Ben
|
Ben
|
||||||
Ben Roberts
|
Ben Roberts
|
||||||
ben-utzer
|
ben-utzer
|
||||||
|
BinkaDroid
|
||||||
|
Bjoessi
|
||||||
bufalo1973
|
bufalo1973
|
||||||
Calango Jr
|
Calango Jr
|
||||||
Carlos Solís
|
Carlos Solís
|
||||||
|
@ -107,6 +112,7 @@ Jens Tautenhahn
|
||||||
jensp
|
jensp
|
||||||
Jeroen De Meerleer
|
Jeroen De Meerleer
|
||||||
jeroenpraat
|
jeroenpraat
|
||||||
|
JOduMonT
|
||||||
Johannes Schwab
|
Johannes Schwab
|
||||||
John Brazil
|
John Brazil
|
||||||
Jonatan Nyberg
|
Jonatan Nyberg
|
||||||
|
@ -175,6 +181,7 @@ R C
|
||||||
Rabuzarus
|
Rabuzarus
|
||||||
Radek
|
Radek
|
||||||
Rafael Garau
|
Rafael Garau
|
||||||
|
Rain Hawk
|
||||||
Rainulf Pineda
|
Rainulf Pineda
|
||||||
Ralf Thees
|
Ralf Thees
|
||||||
Ralph
|
Ralph
|
||||||
|
@ -183,6 +190,7 @@ rcmaniac
|
||||||
rebeka-catalina
|
rebeka-catalina
|
||||||
repat
|
repat
|
||||||
Ricardo Pereira
|
Ricardo Pereira
|
||||||
|
Rik 4
|
||||||
RJ Madsen
|
RJ Madsen
|
||||||
Roland Häder
|
Roland Häder
|
||||||
Rui Andrada
|
Rui Andrada
|
||||||
|
@ -207,6 +215,7 @@ Steffen K9
|
||||||
StefOfficiel
|
StefOfficiel
|
||||||
Sveinn í Felli
|
Sveinn í Felli
|
||||||
Sven Anders
|
Sven Anders
|
||||||
|
Sylke Vicious
|
||||||
Sylvain Lagacé
|
Sylvain Lagacé
|
||||||
szymon.filip
|
szymon.filip
|
||||||
Sérgio Lima
|
Sérgio Lima
|
||||||
|
@ -225,6 +234,7 @@ tomacat
|
||||||
tomamplius
|
tomamplius
|
||||||
tomtom84
|
tomtom84
|
||||||
Tony Baldwin
|
Tony Baldwin
|
||||||
|
Torbjörn Andersson
|
||||||
TORminator
|
TORminator
|
||||||
trebor
|
trebor
|
||||||
tschlotfeldt
|
tschlotfeldt
|
||||||
|
@ -234,6 +244,7 @@ U-SOUND\mike
|
||||||
ufic
|
ufic
|
||||||
Ulf Rompe
|
Ulf Rompe
|
||||||
Unknown
|
Unknown
|
||||||
|
Valvin
|
||||||
Vasudev Kamath
|
Vasudev Kamath
|
||||||
Vasya Novikov
|
Vasya Novikov
|
||||||
Vinzenz Vietzke
|
Vinzenz Vietzke
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2019.06-dev
|
2019.06
|
||||||
|
|
35
boot.php
35
boot.php
|
@ -31,7 +31,7 @@ use Friendica\Util\DateTimeFormat;
|
||||||
|
|
||||||
define('FRIENDICA_PLATFORM', 'Friendica');
|
define('FRIENDICA_PLATFORM', 'Friendica');
|
||||||
define('FRIENDICA_CODENAME', 'Dalmatian Bellflower');
|
define('FRIENDICA_CODENAME', 'Dalmatian Bellflower');
|
||||||
define('FRIENDICA_VERSION', '2019.06-dev');
|
define('FRIENDICA_VERSION', '2019.06');
|
||||||
define('DFRN_PROTOCOL_VERSION', '2.23');
|
define('DFRN_PROTOCOL_VERSION', '2.23');
|
||||||
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
|
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
|
||||||
|
|
||||||
|
@ -535,39 +535,6 @@ function is_site_admin()
|
||||||
return local_user() && $admin_email && in_array(defaults($a->user, 'email', ''), $adminlist);
|
return local_user() && $admin_email && in_array(defaults($a->user, 'email', ''), $adminlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns querystring as string from a mapped array.
|
|
||||||
*
|
|
||||||
* @param array $params mapped array with query parameters
|
|
||||||
* @param string $name of parameter, default null
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function build_querystring($params, $name = null)
|
|
||||||
{
|
|
||||||
$ret = "";
|
|
||||||
foreach ($params as $key => $val) {
|
|
||||||
if (is_array($val)) {
|
|
||||||
/// @TODO maybe not compare against null, use is_null()
|
|
||||||
if ($name == null) {
|
|
||||||
$ret .= build_querystring($val, $key);
|
|
||||||
} else {
|
|
||||||
$ret .= build_querystring($val, $name . "[$key]");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$val = urlencode($val);
|
|
||||||
/// @TODO maybe not compare against null, use is_null()
|
|
||||||
if ($name != null) {
|
|
||||||
/// @TODO two string concated, can be merged to one
|
|
||||||
$ret .= $name . "[$key]" . "=$val&";
|
|
||||||
} else {
|
|
||||||
$ret .= "$key=$val&";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function explode_querystring($query)
|
function explode_querystring($query)
|
||||||
{
|
{
|
||||||
$arg_st = strpos($query, '?');
|
$arg_st = strpos($query, '?');
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"mobiledetect/mobiledetectlib": "2.8.*",
|
"mobiledetect/mobiledetectlib": "2.8.*",
|
||||||
"monolog/monolog": "^1.24",
|
"monolog/monolog": "^1.24",
|
||||||
"nikic/fast-route": "^1.3",
|
"nikic/fast-route": "^1.3",
|
||||||
|
"paragonie/hidden-string": "^1.0",
|
||||||
"pear/text_languagedetect": "1.*",
|
"pear/text_languagedetect": "1.*",
|
||||||
"pragmarx/google2fa": "^5.0",
|
"pragmarx/google2fa": "^5.0",
|
||||||
"pragmarx/recovery": "^0.1.0",
|
"pragmarx/recovery": "^0.1.0",
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
"fxp/composer-asset-plugin": "~1.3",
|
"fxp/composer-asset-plugin": "~1.3",
|
||||||
"bower-asset/base64": "^1.0",
|
"bower-asset/base64": "^1.0",
|
||||||
"bower-asset/chart-js": "^2.7",
|
"bower-asset/chart-js": "^2.7",
|
||||||
|
"bower-asset/dompurify": "^1.0",
|
||||||
"bower-asset/perfect-scrollbar": "^0.6",
|
"bower-asset/perfect-scrollbar": "^0.6",
|
||||||
"bower-asset/vue": "^2.5",
|
"bower-asset/vue": "^2.5",
|
||||||
"npm-asset/jquery": "^2.0",
|
"npm-asset/jquery": "^2.0",
|
||||||
|
@ -95,7 +97,19 @@
|
||||||
},
|
},
|
||||||
"archive": {
|
"archive": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"log", "cache", "/photo", "/proxy"
|
"/.*",
|
||||||
|
"/*file",
|
||||||
|
"!/.htaccess-dist",
|
||||||
|
"/tests",
|
||||||
|
"/*.xml",
|
||||||
|
"/composer.*",
|
||||||
|
"/log",
|
||||||
|
"/cache",
|
||||||
|
"/photo",
|
||||||
|
"/proxy",
|
||||||
|
"/addon",
|
||||||
|
"!/vendor",
|
||||||
|
"!/view/asset"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
179
composer.lock
generated
179
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d7302553201de079b72871c0b2922ce7",
|
"content-hash": "eb985236d64ed0b0fe1fc2e4ac6616e2",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asika/simple-console",
|
"name": "asika/simple-console",
|
||||||
|
@ -148,6 +148,51 @@
|
||||||
"description": "Base64 encoding and decoding",
|
"description": "Base64 encoding and decoding",
|
||||||
"time": "2017-03-25T21:16:21+00:00"
|
"time": "2017-03-25T21:16:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "bower-asset/dompurify",
|
||||||
|
"version": "1.0.10",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cure53/DOMPurify.git",
|
||||||
|
"reference": "b537cab466329b1b077e0e5e3c14edad2b7142f7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cure53/DOMPurify/zipball/b537cab466329b1b077e0e5e3c14edad2b7142f7",
|
||||||
|
"reference": "b537cab466329b1b077e0e5e3c14edad2b7142f7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"type": "bower-asset-library",
|
||||||
|
"extra": {
|
||||||
|
"bower-asset-main": "src/purify.js",
|
||||||
|
"bower-asset-ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"demos",
|
||||||
|
"scripts",
|
||||||
|
"test",
|
||||||
|
"website"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"MPL-2.0",
|
||||||
|
"Apache-2.0"
|
||||||
|
],
|
||||||
|
"description": "A DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG",
|
||||||
|
"keywords": [
|
||||||
|
"cross site scripting",
|
||||||
|
"dom",
|
||||||
|
"filter",
|
||||||
|
"html",
|
||||||
|
"mathml",
|
||||||
|
"sanitize",
|
||||||
|
"sanitizer",
|
||||||
|
"secure",
|
||||||
|
"security",
|
||||||
|
"svg",
|
||||||
|
"xss"
|
||||||
|
],
|
||||||
|
"time": "2019-02-19T13:27:01+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "bower-asset/perfect-scrollbar",
|
"name": "bower-asset/perfect-scrollbar",
|
||||||
"version": "0.6.16",
|
"version": "0.6.16",
|
||||||
|
@ -1175,6 +1220,22 @@
|
||||||
"require": {
|
"require": {
|
||||||
"npm-asset/ev-emitter": ">=1.0.0,<2.0.0"
|
"npm-asset/ev-emitter": ">=1.0.0,<2.0.0"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"npm-asset/chalk": ">=1.1.1,<2.0.0",
|
||||||
|
"npm-asset/cheerio": ">=0.19.0,<0.20.0",
|
||||||
|
"npm-asset/gulp": ">=3.9.0,<4.0.0",
|
||||||
|
"npm-asset/gulp-jshint": ">=1.11.2,<2.0.0",
|
||||||
|
"npm-asset/gulp-json-lint": ">=0.1.0,<0.2.0",
|
||||||
|
"npm-asset/gulp-rename": ">=1.2.2,<2.0.0",
|
||||||
|
"npm-asset/gulp-replace": ">=0.5.4,<0.6.0",
|
||||||
|
"npm-asset/gulp-requirejs-optimize": "dev-github:metafizzy/gulp-requirejs-optimize",
|
||||||
|
"npm-asset/gulp-uglify": ">=1.4.2,<2.0.0",
|
||||||
|
"npm-asset/gulp-util": ">=3.0.7,<4.0.0",
|
||||||
|
"npm-asset/highlight.js": ">=8.9.1,<9.0.0",
|
||||||
|
"npm-asset/marked": ">=0.3.5,<0.4.0",
|
||||||
|
"npm-asset/minimist": ">=1.2.0,<2.0.0",
|
||||||
|
"npm-asset/transfob": ">=1.0.0,<2.0.0"
|
||||||
|
},
|
||||||
"type": "npm-asset-library",
|
"type": "npm-asset-library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"npm-asset-bugs": {
|
"npm-asset-bugs": {
|
||||||
|
@ -1220,6 +1281,14 @@
|
||||||
"reference": null,
|
"reference": null,
|
||||||
"shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3"
|
"shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"npm-asset/grunt": "~0.4.2",
|
||||||
|
"npm-asset/grunt-contrib-cssmin": "~0.9.0",
|
||||||
|
"npm-asset/grunt-contrib-jshint": "~0.6.3",
|
||||||
|
"npm-asset/grunt-contrib-less": "~0.11.0",
|
||||||
|
"npm-asset/grunt-contrib-uglify": "~0.4.0",
|
||||||
|
"npm-asset/grunt-contrib-watch": "~0.6.1"
|
||||||
|
},
|
||||||
"type": "npm-asset-library",
|
"type": "npm-asset-library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"npm-asset-bugs": {
|
"npm-asset-bugs": {
|
||||||
|
@ -1253,6 +1322,32 @@
|
||||||
"reference": null,
|
"reference": null,
|
||||||
"shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02"
|
"shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"npm-asset/commitplease": "2.0.0",
|
||||||
|
"npm-asset/core-js": "0.9.17",
|
||||||
|
"npm-asset/grunt": "0.4.5",
|
||||||
|
"npm-asset/grunt-babel": "5.0.1",
|
||||||
|
"npm-asset/grunt-cli": "0.1.13",
|
||||||
|
"npm-asset/grunt-compare-size": "0.4.0",
|
||||||
|
"npm-asset/grunt-contrib-jshint": "0.11.2",
|
||||||
|
"npm-asset/grunt-contrib-uglify": "0.9.2",
|
||||||
|
"npm-asset/grunt-contrib-watch": "0.6.1",
|
||||||
|
"npm-asset/grunt-git-authors": "2.0.1",
|
||||||
|
"npm-asset/grunt-jscs": "2.1.0",
|
||||||
|
"npm-asset/grunt-jsonlint": "1.0.4",
|
||||||
|
"npm-asset/grunt-npmcopy": "0.1.0",
|
||||||
|
"npm-asset/gzip-js": "0.3.2",
|
||||||
|
"npm-asset/jsdom": "5.6.1",
|
||||||
|
"npm-asset/load-grunt-tasks": "1.0.0",
|
||||||
|
"npm-asset/qunit-assert-step": "1.0.3",
|
||||||
|
"npm-asset/qunitjs": "1.17.1",
|
||||||
|
"npm-asset/requirejs": "2.1.17",
|
||||||
|
"npm-asset/sinon": "1.10.3",
|
||||||
|
"npm-asset/sizzle": "2.2.1",
|
||||||
|
"npm-asset/strip-json-comments": "1.0.3",
|
||||||
|
"npm-asset/testswarm": "1.1.0",
|
||||||
|
"npm-asset/win-spawn": "2.0.0"
|
||||||
|
},
|
||||||
"type": "npm-asset-library",
|
"type": "npm-asset-library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"npm-asset-bugs": {
|
"npm-asset-bugs": {
|
||||||
|
@ -1403,6 +1498,12 @@
|
||||||
"reference": null,
|
"reference": null,
|
||||||
"shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5"
|
"shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"npm-asset/grunt": "~0.4.1",
|
||||||
|
"npm-asset/grunt-contrib-connect": "~0.5.0",
|
||||||
|
"npm-asset/grunt-contrib-jshint": "~0.7.1",
|
||||||
|
"npm-asset/grunt-contrib-uglify": "~0.2.7"
|
||||||
|
},
|
||||||
"type": "npm-asset-library",
|
"type": "npm-asset-library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"npm-asset-bugs": {
|
"npm-asset-bugs": {
|
||||||
|
@ -1622,25 +1723,24 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "paragonie/constant_time_encoding",
|
"name": "paragonie/constant_time_encoding",
|
||||||
"version": "v1.0.4",
|
"version": "v2.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/paragonie/constant_time_encoding.git",
|
"url": "https://github.com/paragonie/constant_time_encoding.git",
|
||||||
"reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6"
|
"reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
|
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/55af0dc01992b4d0da7f6372e2eac097bbbaffdb",
|
||||||
"reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
|
"reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^5.3|^7"
|
"php": "^7"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"paragonie/random_compat": "^1.4|^2",
|
"phpunit/phpunit": "^6|^7",
|
||||||
"phpunit/phpunit": "4.*|5.*",
|
"vimeo/psalm": "^1|^2"
|
||||||
"vimeo/psalm": "^0.3|^1"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -1681,7 +1781,56 @@
|
||||||
"hex2bin",
|
"hex2bin",
|
||||||
"rfc4648"
|
"rfc4648"
|
||||||
],
|
],
|
||||||
"time": "2018-04-30T17:57:16+00:00"
|
"time": "2019-01-03T20:26:31+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "paragonie/hidden-string",
|
||||||
|
"version": "v1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/paragonie/hidden-string.git",
|
||||||
|
"reference": "0bbb00be0e33b8e1d48fa79ea35cd42d3091a936"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/paragonie/hidden-string/zipball/0bbb00be0e33b8e1d48fa79ea35cd42d3091a936",
|
||||||
|
"reference": "0bbb00be0e33b8e1d48fa79ea35cd42d3091a936",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"paragonie/constant_time_encoding": "^2",
|
||||||
|
"paragonie/sodium_compat": "^1.6",
|
||||||
|
"php": "^7"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^6|^7",
|
||||||
|
"vimeo/psalm": "^1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"ParagonIE\\HiddenString\\": "./src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MPL-2.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Paragon Initiative Enterprises",
|
||||||
|
"email": "info@paragonie.com",
|
||||||
|
"homepage": "https://paragonie.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Encapsulate strings in an object to hide them from stack traces",
|
||||||
|
"homepage": "https://github.com/paragonie/hidden-string",
|
||||||
|
"keywords": [
|
||||||
|
"hidden",
|
||||||
|
"stack trace",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"time": "2018-05-07T20:28:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "paragonie/random_compat",
|
"name": "paragonie/random_compat",
|
||||||
|
@ -3600,7 +3749,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Provides the functionality to compare PHP values for equality",
|
"description": "Provides the functionality to compare PHP values for equality",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/comparator",
|
"homepage": "https://github.com/sebastianbergmann/comparator",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"comparator",
|
"comparator",
|
||||||
"compare",
|
"compare",
|
||||||
|
@ -3702,7 +3851,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Provides functionality to handle HHVM/PHP environments",
|
"description": "Provides functionality to handle HHVM/PHP environments",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/environment",
|
"homepage": "https://github.com/sebastianbergmann/environment",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Xdebug",
|
"Xdebug",
|
||||||
"environment",
|
"environment",
|
||||||
|
@ -3770,7 +3919,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Provides the functionality to export PHP variables for visualization",
|
"description": "Provides the functionality to export PHP variables for visualization",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/exporter",
|
"homepage": "https://github.com/sebastianbergmann/exporter",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"export",
|
"export",
|
||||||
"exporter"
|
"exporter"
|
||||||
|
@ -3822,7 +3971,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Snapshotting of global state",
|
"description": "Snapshotting of global state",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/global-state",
|
"homepage": "https://github.com/sebastianbergmann/global-state",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"global state"
|
"global state"
|
||||||
],
|
],
|
||||||
|
@ -3924,7 +4073,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Provides functionality to recursively process PHP variables",
|
"description": "Provides functionality to recursively process PHP variables",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
"homepage": "https://github.com/sebastianbergmann/recursion-context",
|
||||||
"time": "2016-11-19T07:33:16+00:00"
|
"time": "2016-11-19T07:33:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,7 @@ return [
|
||||||
// logfile (String)
|
// logfile (String)
|
||||||
// The logfile for storing logs.
|
// The logfile for storing logs.
|
||||||
// Can be a full path or a relative path to the Friendica home directory
|
// Can be a full path or a relative path to the Friendica home directory
|
||||||
'logfile' => 'friendica.log',
|
'logfile' => 'log/friendica.log',
|
||||||
|
|
||||||
// loglevel (String)
|
// loglevel (String)
|
||||||
// The loglevel for all logs.
|
// The loglevel for all logs.
|
||||||
|
|
|
@ -358,6 +358,7 @@ Called from `Emailer::send()` before building the mime message.
|
||||||
- **htmlVersion**: html version of the message
|
- **htmlVersion**: html version of the message
|
||||||
- **textVersion**: text only version of the message
|
- **textVersion**: text only version of the message
|
||||||
- **additionalMailHeader**: additions to the smtp mail header
|
- **additionalMailHeader**: additions to the smtp mail header
|
||||||
|
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
|
||||||
|
|
||||||
### emailer_send
|
### emailer_send
|
||||||
Called before calling PHP's `mail()`.
|
Called before calling PHP's `mail()`.
|
||||||
|
@ -367,6 +368,7 @@ Called before calling PHP's `mail()`.
|
||||||
- **subject**
|
- **subject**
|
||||||
- **body**
|
- **body**
|
||||||
- **headers**
|
- **headers**
|
||||||
|
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
|
||||||
|
|
||||||
### load_config
|
### load_config
|
||||||
Called during `App` initialization to allow addons to load their own configuration file(s) with `App::loadConfigFile()`.
|
Called during `App` initialization to allow addons to load their own configuration file(s) with `App::loadConfigFile()`.
|
||||||
|
|
15
doc/FAQ.md
15
doc/FAQ.md
|
@ -126,16 +126,15 @@ A **hidden contact** will not be displayed in any "friend list" (except to you).
|
||||||
However a hidden contact will appear normally in conversations and this may expose his/her hidden status to anybody who can see the conversation.
|
However a hidden contact will appear normally in conversations and this may expose his/her hidden status to anybody who can see the conversation.
|
||||||
|
|
||||||
<a name="removed"></a>
|
<a name="removed"></a>
|
||||||
### What happens when an account is removed? Is it truly deleted?
|
### What happens when an account is removed?
|
||||||
|
|
||||||
If you delete your account, we will immediately remove all your content on **your** server.
|
If you remove your account, it will be scheduled for permanent deletion in *seven days*.
|
||||||
|
As soon as you activate the deletion process you won't be able to login any more.
|
||||||
|
Only the administrator of your node can halt this process prior to permanent deletion.
|
||||||
|
|
||||||
Then Friendica issues requests to all your contacts to remove you.
|
After the elapsed time of seven days, all your posts, messages, photos, and personal information stored on your node will be deleted.
|
||||||
This will also remove you from the global directory.
|
Your node will also issue removal requests to all your contacts; this will also remove your profile from the global directory if you are listed.
|
||||||
Doing this requires your account and profile still to be "partially" available for up to 24 hours in order to establish contact with all your friends.
|
Your username cannot be reissued for future sign-ups for security reasons.
|
||||||
We can block it in several ways so that it appears empty and all profile information erased, but will then wait for 24 hours (or after all of your contacts have been notified) before we can physically remove it.
|
|
||||||
|
|
||||||
After that, your account is deleted.
|
|
||||||
|
|
||||||
<a name="hashtag"></a>
|
<a name="hashtag"></a>
|
||||||
### Can I follow a hashtag?
|
### Can I follow a hashtag?
|
||||||
|
|
|
@ -361,7 +361,7 @@ function api_call(App $a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call']);
|
Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => $a->query_string]);
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
} catch (HTTPException $e) {
|
} catch (HTTPException $e) {
|
||||||
header("HTTP/1.1 {$e->getCode()} {$e->httpdesc}");
|
header("HTTP/1.1 {$e->getCode()} {$e->httpdesc}");
|
||||||
|
@ -611,7 +611,7 @@ function api_get_user(App $a, $contact_id = null)
|
||||||
'name' => $contact["name"],
|
'name' => $contact["name"],
|
||||||
'screen_name' => (($contact['nick']) ? $contact['nick'] : $contact['name']),
|
'screen_name' => (($contact['nick']) ? $contact['nick'] : $contact['name']),
|
||||||
'location' => ($contact["location"] != "") ? $contact["location"] : ContactSelector::networkToName($contact['network'], $contact['url']),
|
'location' => ($contact["location"] != "") ? $contact["location"] : ContactSelector::networkToName($contact['network'], $contact['url']),
|
||||||
'description' => $contact["about"],
|
'description' => HTML::toPlaintext(BBCode::toPlaintext($contact["about"])),
|
||||||
'profile_image_url' => $contact["micro"],
|
'profile_image_url' => $contact["micro"],
|
||||||
'profile_image_url_https' => $contact["micro"],
|
'profile_image_url_https' => $contact["micro"],
|
||||||
'profile_image_url_profile_size' => $contact["thumb"],
|
'profile_image_url_profile_size' => $contact["thumb"],
|
||||||
|
@ -690,7 +690,7 @@ function api_get_user(App $a, $contact_id = null)
|
||||||
'name' => (($uinfo[0]['name']) ? $uinfo[0]['name'] : $uinfo[0]['nick']),
|
'name' => (($uinfo[0]['name']) ? $uinfo[0]['name'] : $uinfo[0]['nick']),
|
||||||
'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']),
|
'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']),
|
||||||
'location' => $location,
|
'location' => $location,
|
||||||
'description' => $description,
|
'description' => HTML::toPlaintext(BBCode::toPlaintext($description)),
|
||||||
'profile_image_url' => $uinfo[0]['micro'],
|
'profile_image_url' => $uinfo[0]['micro'],
|
||||||
'profile_image_url_https' => $uinfo[0]['micro'],
|
'profile_image_url_https' => $uinfo[0]['micro'],
|
||||||
'profile_image_url_profile_size' => $uinfo[0]["thumb"],
|
'profile_image_url_profile_size' => $uinfo[0]["thumb"],
|
||||||
|
@ -1271,7 +1271,7 @@ function api_status_show($type, $item_id)
|
||||||
function api_get_last_status($ownerId, $uid)
|
function api_get_last_status($ownerId, $uid)
|
||||||
{
|
{
|
||||||
$condition = [
|
$condition = [
|
||||||
'owner-id' => $ownerId,
|
'author-id'=> $ownerId,
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
|
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
|
||||||
'private' => false
|
'private' => false
|
||||||
|
|
|
@ -446,80 +446,3 @@ function drop_item($id, $return = '')
|
||||||
//NOTREACHED
|
//NOTREACHED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* arrange the list in years */
|
|
||||||
function list_post_dates($uid, $wall)
|
|
||||||
{
|
|
||||||
$dnow = DateTimeFormat::localNow('Y-m-d');
|
|
||||||
|
|
||||||
$dthen = Item::firstPostDate($uid, $wall);
|
|
||||||
if (!$dthen) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the start and end date to the beginning of the month
|
|
||||||
$dnow = substr($dnow, 0, 8) . '01';
|
|
||||||
$dthen = substr($dthen, 0, 8) . '01';
|
|
||||||
|
|
||||||
$ret = [];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Starting with the current month, get the first and last days of every
|
|
||||||
* month down to and including the month of the first post
|
|
||||||
*/
|
|
||||||
while (substr($dnow, 0, 7) >= substr($dthen, 0, 7)) {
|
|
||||||
$dyear = intval(substr($dnow, 0, 4));
|
|
||||||
$dstart = substr($dnow, 0, 8) . '01';
|
|
||||||
$dend = substr($dnow, 0, 8) . Temporal::getDaysInMonth(intval($dnow), intval(substr($dnow, 5)));
|
|
||||||
$start_month = DateTimeFormat::utc($dstart, 'Y-m-d');
|
|
||||||
$end_month = DateTimeFormat::utc($dend, 'Y-m-d');
|
|
||||||
$str = L10n::getDay(DateTimeFormat::utc($dnow, 'F'));
|
|
||||||
|
|
||||||
if (empty($ret[$dyear])) {
|
|
||||||
$ret[$dyear] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret[$dyear][] = [$str, $end_month, $start_month];
|
|
||||||
$dnow = DateTimeFormat::utc($dnow . ' -1 month', 'Y-m-d');
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function posted_date_widget($url, $uid, $wall)
|
|
||||||
{
|
|
||||||
$o = '';
|
|
||||||
|
|
||||||
if (!Feature::isEnabled($uid, 'archives')) {
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For former Facebook folks that left because of "timeline"
|
|
||||||
/*
|
|
||||||
* @TODO old-lost code?
|
|
||||||
if ($wall && intval(PConfig::get($uid, 'system', 'no_wall_archive_widget')))
|
|
||||||
return $o;
|
|
||||||
*/
|
|
||||||
|
|
||||||
$visible_years = PConfig::get($uid, 'system', 'archive_visible_years', 5);
|
|
||||||
|
|
||||||
$ret = list_post_dates($uid, $wall);
|
|
||||||
|
|
||||||
if (!DBA::isResult($ret)) {
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cutoff_year = intval(DateTimeFormat::localNow('Y')) - $visible_years;
|
|
||||||
$cutoff = ((array_key_exists($cutoff_year, $ret))? true : false);
|
|
||||||
|
|
||||||
$o = Renderer::replaceMacros(Renderer::getMarkupTemplate('posted_date_widget.tpl'),[
|
|
||||||
'$title' => L10n::t('Archives'),
|
|
||||||
'$size' => $visible_years,
|
|
||||||
'$cutoff_year' => $cutoff_year,
|
|
||||||
'$cutoff' => $cutoff,
|
|
||||||
'$url' => $url,
|
|
||||||
'$dates' => $ret,
|
|
||||||
'$showmore' => L10n::t('show more')
|
|
||||||
|
|
||||||
]);
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,10 +8,8 @@ use Friendica\Content\Smilies;
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Core\Protocol;
|
use Friendica\Core\Protocol;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
|
|
||||||
use Friendica\Model\FileTag;
|
use Friendica\Model\FileTag;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\XML;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn user/group ACLs stored as angle bracketed text into arrays
|
* Turn user/group ACLs stored as angle bracketed text into arrays
|
||||||
|
@ -186,21 +184,17 @@ function get_cats_and_terms($item)
|
||||||
{
|
{
|
||||||
$categories = [];
|
$categories = [];
|
||||||
$folders = [];
|
$folders = [];
|
||||||
|
|
||||||
$matches = [];
|
|
||||||
$first = true;
|
$first = true;
|
||||||
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
|
|
||||||
if ($cnt) {
|
foreach (FileTag::fileToArray($item['file'] ?? '', 'category') as $savedFolderName) {
|
||||||
foreach ($matches as $mtch) {
|
$categories[] = [
|
||||||
$categories[] = [
|
'name' => $savedFolderName,
|
||||||
'name' => XML::escape(FileTag::decode($mtch[1])),
|
'url' => "#",
|
||||||
'url' => "#",
|
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&cat=' . rawurlencode($savedFolderName) : ""),
|
||||||
'removeurl' => ((local_user() == $item['uid'])?'filerm/' . $item['id'] . '?f=&cat=' . XML::escape(FileTag::decode($mtch[1])):""),
|
'first' => $first,
|
||||||
'first' => $first,
|
'last' => false
|
||||||
'last' => false
|
];
|
||||||
];
|
$first = false;
|
||||||
$first = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($categories)) {
|
if (count($categories)) {
|
||||||
|
@ -208,20 +202,15 @@ function get_cats_and_terms($item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_user() == $item['uid']) {
|
if (local_user() == $item['uid']) {
|
||||||
$matches = [];
|
foreach (FileTag::fileToArray($item['file'] ?? '') as $savedFolderName) {
|
||||||
$first = true;
|
$folders[] = [
|
||||||
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
|
'name' => $savedFolderName,
|
||||||
if ($cnt) {
|
'url' => "#",
|
||||||
foreach ($matches as $mtch) {
|
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&term=' . rawurlencode($savedFolderName) : ""),
|
||||||
$folders[] = [
|
'first' => $first,
|
||||||
'name' => XML::escape(FileTag::decode($mtch[1])),
|
'last' => false
|
||||||
'url' => "#",
|
];
|
||||||
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&term=' . XML::escape(FileTag::decode($mtch[1])) : ""),
|
$first = false;
|
||||||
'first' => $first,
|
|
||||||
'last' => false
|
|
||||||
];
|
|
||||||
$first = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ function cal_content(App $a)
|
||||||
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
|
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
|
||||||
|
|
||||||
// get the tab navigation bar
|
// get the tab navigation bar
|
||||||
$tabs = Profile::getTabs($a, false, $a->data['user']['nickname']);
|
$tabs = Profile::getTabs($a, 'cal', false, $a->data['user']['nickname']);
|
||||||
|
|
||||||
// The view mode part is similiar to /mod/events.php
|
// The view mode part is similiar to /mod/events.php
|
||||||
if ($mode == 'view') {
|
if ($mode == 'view') {
|
||||||
|
|
|
@ -209,7 +209,7 @@ function dfrn_confirm_post(App $a, $handsfree = null)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$res = Network::post($dfrn_confirm, $params, null, $redirects, 120)->getBody();
|
$res = Network::post($dfrn_confirm, $params, [], 120)->getBody();
|
||||||
|
|
||||||
Logger::log(' Confirm: received data: ' . $res, Logger::DATA);
|
Logger::log(' Confirm: received data: ' . $res, Logger::DATA);
|
||||||
|
|
||||||
|
|
|
@ -190,13 +190,13 @@ function dfrn_dispatch_public($postdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the corresponding public contact
|
// Fetch the corresponding public contact
|
||||||
$contact = Contact::getDetailsByAddr($msg['author'], 0);
|
$contact_id = Contact::getIdForURL($msg['author']);
|
||||||
if (!$contact) {
|
if (empty($contact_id)) {
|
||||||
Logger::log('Contact not found for address ' . $msg['author']);
|
Logger::log('Contact not found for address ' . $msg['author']);
|
||||||
System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found');
|
System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$importer = DFRN::getImporter($contact['id']);
|
$importer = DFRN::getImporter($contact_id);
|
||||||
|
|
||||||
// This should never fail
|
// This should never fail
|
||||||
if (empty($importer)) {
|
if (empty($importer)) {
|
||||||
|
|
|
@ -476,7 +476,7 @@ function dfrn_request_post(App $a)
|
||||||
|
|
||||||
function dfrn_request_content(App $a)
|
function dfrn_request_content(App $a)
|
||||||
{
|
{
|
||||||
if (($a->argc != 2) || (!count($a->profile))) {
|
if ($a->argc != 2 || empty($a->profile)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
265
mod/dirfind.php
265
mod/dirfind.php
|
@ -1,265 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @file mod/dirfind.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Friendica\App;
|
|
||||||
use Friendica\Content\ContactSelector;
|
|
||||||
use Friendica\Content\Pager;
|
|
||||||
use Friendica\Content\Widget;
|
|
||||||
use Friendica\Core\Config;
|
|
||||||
use Friendica\Core\L10n;
|
|
||||||
use Friendica\Core\Protocol;
|
|
||||||
use Friendica\Core\Renderer;
|
|
||||||
use Friendica\Core\System;
|
|
||||||
use Friendica\Core\Worker;
|
|
||||||
use Friendica\Database\DBA;
|
|
||||||
use Friendica\Model;
|
|
||||||
use Friendica\Module;
|
|
||||||
use Friendica\Network\Probe;
|
|
||||||
use Friendica\Protocol\PortableContact;
|
|
||||||
use Friendica\Util\Network;
|
|
||||||
use Friendica\Util\Proxy as ProxyUtils;
|
|
||||||
use Friendica\Util\Strings;
|
|
||||||
|
|
||||||
|
|
||||||
function dirfind_init(App $a) {
|
|
||||||
|
|
||||||
if (! local_user()) {
|
|
||||||
notice(L10n::t('Permission denied.') . EOL );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($a->page['aside'])) {
|
|
||||||
$a->page['aside'] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$a->page['aside'] .= Widget::findPeople();
|
|
||||||
|
|
||||||
$a->page['aside'] .= Widget::follow();
|
|
||||||
}
|
|
||||||
|
|
||||||
function dirfind_content(App $a, $prefix = "") {
|
|
||||||
|
|
||||||
$community = false;
|
|
||||||
$discover_user = false;
|
|
||||||
|
|
||||||
$local = Config::get('system','poco_local_search');
|
|
||||||
|
|
||||||
$search = $prefix.Strings::escapeTags(trim(defaults($_REQUEST, 'search', '')));
|
|
||||||
|
|
||||||
$header = '';
|
|
||||||
|
|
||||||
if (strpos($search,'@') === 0) {
|
|
||||||
$search = substr($search,1);
|
|
||||||
$header = L10n::t('People Search - %s', $search);
|
|
||||||
if ((filter_var($search, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($search)) ||
|
|
||||||
(substr(Strings::normaliseLink($search), 0, 7) == "http://")) {
|
|
||||||
$user_data = Probe::uri($search);
|
|
||||||
$discover_user = (in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($search,'!') === 0) {
|
|
||||||
$search = substr($search,1);
|
|
||||||
$community = true;
|
|
||||||
$header = L10n::t('Forum Search - %s', $search);
|
|
||||||
}
|
|
||||||
|
|
||||||
$o = '';
|
|
||||||
|
|
||||||
if ($search) {
|
|
||||||
$pager = new Pager($a->query_string);
|
|
||||||
|
|
||||||
if ($discover_user) {
|
|
||||||
$j = new stdClass();
|
|
||||||
$j->total = 1;
|
|
||||||
$j->items_page = 1;
|
|
||||||
$j->page = $pager->getPage();
|
|
||||||
|
|
||||||
$objresult = new stdClass();
|
|
||||||
$objresult->cid = 0;
|
|
||||||
$objresult->name = $user_data["name"];
|
|
||||||
$objresult->addr = $user_data["addr"];
|
|
||||||
$objresult->url = $user_data["url"];
|
|
||||||
$objresult->photo = $user_data["photo"];
|
|
||||||
$objresult->tags = "";
|
|
||||||
$objresult->network = $user_data["network"];
|
|
||||||
|
|
||||||
$contact = Model\Contact::getDetailsByURL($user_data["url"], local_user());
|
|
||||||
$objresult->cid = $contact["cid"];
|
|
||||||
$objresult->pcid = $contact["zid"];
|
|
||||||
|
|
||||||
$j->results[] = $objresult;
|
|
||||||
|
|
||||||
// Add the contact to the global contacts if it isn't already in our system
|
|
||||||
if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) {
|
|
||||||
Model\GContact::update($user_data);
|
|
||||||
}
|
|
||||||
} elseif ($local) {
|
|
||||||
if ($community) {
|
|
||||||
$extra_sql = " AND `community`";
|
|
||||||
} else {
|
|
||||||
$extra_sql = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
$pager->setItemsPerPage(80);
|
|
||||||
|
|
||||||
if (Config::get('system','diaspora_enabled')) {
|
|
||||||
$diaspora = Protocol::DIASPORA;
|
|
||||||
} else {
|
|
||||||
$diaspora = Protocol::DFRN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config::get('system','ostatus_disabled')) {
|
|
||||||
$ostatus = Protocol::OSTATUS;
|
|
||||||
} else {
|
|
||||||
$ostatus = Protocol::DFRN;
|
|
||||||
}
|
|
||||||
|
|
||||||
$search2 = "%".$search."%";
|
|
||||||
|
|
||||||
/// @TODO These 2 SELECTs are not checked on validity with DBA::isResult()
|
|
||||||
$count = q("SELECT count(*) AS `total` FROM `gcontact`
|
|
||||||
WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND
|
|
||||||
((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
|
|
||||||
(`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
|
|
||||||
`addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql",
|
|
||||||
DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora),
|
|
||||||
DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
|
|
||||||
DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)));
|
|
||||||
|
|
||||||
$results = q("SELECT `nurl`
|
|
||||||
FROM `gcontact`
|
|
||||||
WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s', '%s') AND
|
|
||||||
((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
|
|
||||||
(`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
|
|
||||||
`addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql
|
|
||||||
GROUP BY `nurl`
|
|
||||||
ORDER BY `updated` DESC LIMIT %d, %d",
|
|
||||||
DBA::escape(Protocol::ACTIVITYPUB), DBA::escape(Protocol::DFRN), DBA::escape($ostatus), DBA::escape($diaspora),
|
|
||||||
DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
|
|
||||||
DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)), DBA::escape(Strings::escapeHtml($search2)),
|
|
||||||
$pager->getStart(), $pager->getItemsPerPage());
|
|
||||||
$j = new stdClass();
|
|
||||||
$j->total = $count[0]["total"];
|
|
||||||
$j->items_page = $pager->getItemsPerPage();
|
|
||||||
$j->page = $pager->getPage();
|
|
||||||
foreach ($results AS $result) {
|
|
||||||
if (PortableContact::alternateOStatusUrl($result["nurl"])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urlparts = parse_url($result["nurl"]);
|
|
||||||
|
|
||||||
// Ignore results that look strange.
|
|
||||||
// For historic reasons the gcontact table does contain some garbage.
|
|
||||||
if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = Model\Contact::getDetailsByURL($result["nurl"], local_user());
|
|
||||||
|
|
||||||
if ($result["name"] == "") {
|
|
||||||
$result["name"] = end(explode("/", $urlparts["path"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
$objresult = new stdClass();
|
|
||||||
$objresult->cid = $result["cid"];
|
|
||||||
$objresult->pcid = $result["zid"];
|
|
||||||
$objresult->name = $result["name"];
|
|
||||||
$objresult->addr = $result["addr"];
|
|
||||||
$objresult->url = $result["url"];
|
|
||||||
$objresult->photo = $result["photo"];
|
|
||||||
$objresult->tags = $result["keywords"];
|
|
||||||
$objresult->network = $result["network"];
|
|
||||||
|
|
||||||
$j->results[] = $objresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add found profiles from the global directory to the local directory
|
|
||||||
Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search));
|
|
||||||
} elseif (strlen(Config::get('system','directory'))) {
|
|
||||||
$p = (($pager->getPage() != 1) ? '&p=' . $pager->getPage() : '');
|
|
||||||
|
|
||||||
$x = Network::fetchUrl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
|
|
||||||
|
|
||||||
$j = json_decode($x);
|
|
||||||
$pager->setItemsPerPage($j->items_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($j->results)) {
|
|
||||||
$id = 0;
|
|
||||||
|
|
||||||
$entries = [];
|
|
||||||
foreach ($j->results as $jj) {
|
|
||||||
|
|
||||||
$alt_text = "";
|
|
||||||
|
|
||||||
$contact_details = Model\Contact::getDetailsByURL($jj->url, local_user());
|
|
||||||
|
|
||||||
$itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url);
|
|
||||||
|
|
||||||
// If We already know this contact then don't show the "connect" button
|
|
||||||
if ($jj->cid > 0) {
|
|
||||||
$connlnk = "";
|
|
||||||
$conntxt = "";
|
|
||||||
$contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]);
|
|
||||||
if (DBA::isResult($contact)) {
|
|
||||||
$photo_menu = Model\Contact::photoMenu($contact);
|
|
||||||
$details = Module\Contact::getContactTemplateVars($contact);
|
|
||||||
$alt_text = $details['alt_text'];
|
|
||||||
} else {
|
|
||||||
$photo_menu = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$connlnk = System::baseUrl().'/follow/?url='.(!empty($jj->connect) ? $jj->connect : $jj->url);
|
|
||||||
$conntxt = L10n::t('Connect');
|
|
||||||
|
|
||||||
$contact = DBA::selectFirst('contact', [], ['id' => $jj->pcid]);
|
|
||||||
if (DBA::isResult($contact)) {
|
|
||||||
$photo_menu = Model\Contact::photoMenu($contact);
|
|
||||||
} else {
|
|
||||||
$photo_menu = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($jj->url)];
|
|
||||||
$photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk];
|
|
||||||
}
|
|
||||||
|
|
||||||
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
|
|
||||||
|
|
||||||
$entry = [
|
|
||||||
'alt_text' => $alt_text,
|
|
||||||
'url' => Model\Contact::magicLink($jj->url),
|
|
||||||
'itemurl' => $itemurl,
|
|
||||||
'name' => $jj->name,
|
|
||||||
'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB),
|
|
||||||
'img_hover' => $jj->tags,
|
|
||||||
'conntxt' => $conntxt,
|
|
||||||
'connlnk' => $connlnk,
|
|
||||||
'photo_menu' => $photo_menu,
|
|
||||||
'details' => $contact_details['location'],
|
|
||||||
'tags' => $contact_details['keywords'],
|
|
||||||
'about' => $contact_details['about'],
|
|
||||||
'account_type' => Model\Contact::getAccountType($contact_details),
|
|
||||||
'network' => ContactSelector::networkToName($jj->network, $jj->url),
|
|
||||||
'id' => ++$id,
|
|
||||||
];
|
|
||||||
$entries[] = $entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl');
|
|
||||||
$o .= Renderer::replaceMacros($tpl,[
|
|
||||||
'title' => $header,
|
|
||||||
'$contacts' => $entries,
|
|
||||||
'$paginate' => $pager->renderFull($j->total),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
info(L10n::t('No matches') . EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return $o;
|
|
||||||
}
|
|
|
@ -84,6 +84,10 @@ function display_init(App $a)
|
||||||
displayShowFeed($item['id'], $a->argc > 3 && $a->argv[3] == 'conversation.atom');
|
displayShowFeed($item['id'], $a->argc > 3 && $a->argv[3] == 'conversation.atom');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($a->argc >= 3 && $nick == 'feed-item') {
|
||||||
|
displayShowFeed($item['id'], $a->argc > 3 && $a->argv[3] == 'conversation.atom');
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($_SERVER['HTTP_ACCEPT']) && strstr($_SERVER['HTTP_ACCEPT'], 'application/atom+xml')) {
|
if (!empty($_SERVER['HTTP_ACCEPT']) && strstr($_SERVER['HTTP_ACCEPT'], 'application/atom+xml')) {
|
||||||
Logger::log('Directly serving XML for id '.$item["id"], Logger::DEBUG);
|
Logger::log('Directly serving XML for id '.$item["id"], Logger::DEBUG);
|
||||||
displayShowFeed($item["id"], false);
|
displayShowFeed($item["id"], false);
|
||||||
|
@ -186,16 +190,7 @@ function display_fetchauthor($a, $item)
|
||||||
|
|
||||||
$profiledata["photo"] = System::removedBaseUrl($profiledata["photo"]);
|
$profiledata["photo"] = System::removedBaseUrl($profiledata["photo"]);
|
||||||
|
|
||||||
if (local_user()) {
|
return $profiledata;
|
||||||
if (in_array($profiledata["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
|
|
||||||
$profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]);
|
|
||||||
}
|
|
||||||
} elseif ($profiledata["network"] == Protocol::DFRN) {
|
|
||||||
$connect = str_replace("/profile/", "/dfrn_request/", $profiledata["url"]);
|
|
||||||
$profiledata["remoteconnect"] = $connect;
|
|
||||||
}
|
|
||||||
|
|
||||||
return($profiledata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function display_content(App $a, $update = false, $update_uid = 0)
|
function display_content(App $a, $update = false, $update_uid = 0)
|
||||||
|
|
|
@ -21,6 +21,7 @@ use Friendica\Module\Login;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\Temporal;
|
use Friendica\Util\Temporal;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
function events_init(App $a)
|
function events_init(App $a)
|
||||||
{
|
{
|
||||||
|
@ -195,7 +196,7 @@ function events_post(App $a)
|
||||||
$item_id = Event::store($datarray);
|
$item_id = Event::store($datarray);
|
||||||
|
|
||||||
if (!$cid) {
|
if (!$cid) {
|
||||||
Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
|
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::POST, $item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$a->internalRedirect('events');
|
$a->internalRedirect('events');
|
||||||
|
@ -246,7 +247,7 @@ function events_content(App $a)
|
||||||
$tabs = '';
|
$tabs = '';
|
||||||
// tabs
|
// tabs
|
||||||
if ($a->theme_events_in_profile) {
|
if ($a->theme_events_in_profile) {
|
||||||
$tabs = Profile::getTabs($a, true);
|
$tabs = Profile::getTabs($a, 'events', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$mode = 'view';
|
$mode = 'view';
|
||||||
|
|
|
@ -10,6 +10,7 @@ use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
function fsuggest_post(App $a)
|
function fsuggest_post(App $a)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +52,7 @@ function fsuggest_post(App $a)
|
||||||
'photo' => $contact['avatar'], 'note' => $note, 'created' => DateTimeFormat::utcNow()];
|
'photo' => $contact['avatar'], 'note' => $note, 'created' => DateTimeFormat::utcNow()];
|
||||||
DBA::insert('fsuggest', $fields);
|
DBA::insert('fsuggest', $fields);
|
||||||
|
|
||||||
Worker::add(PRIORITY_HIGH, 'Notifier', 'suggest', DBA::lastInsertId());
|
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::SUGGESTION, DBA::lastInsertId());
|
||||||
|
|
||||||
info(L10n::t('Friend suggestion sent.') . EOL);
|
info(L10n::t('Friend suggestion sent.') . EOL);
|
||||||
}
|
}
|
||||||
|
|
17
mod/item.php
17
mod/item.php
|
@ -27,12 +27,12 @@ use Friendica\Core\Protocol;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Model\Attach;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Conversation;
|
use Friendica\Model\Conversation;
|
||||||
use Friendica\Model\FileTag;
|
use Friendica\Model\FileTag;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Attach;
|
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Term;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
use Friendica\Protocol\Email;
|
use Friendica\Protocol\Email;
|
||||||
|
@ -40,6 +40,7 @@ use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Emailer;
|
use Friendica\Util\Emailer;
|
||||||
use Friendica\Util\Security;
|
use Friendica\Util\Security;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
require_once 'include/items.php';
|
require_once 'include/items.php';
|
||||||
|
|
||||||
|
@ -327,10 +328,9 @@ function item_post(App $a) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($categories))
|
if (!empty($categories)) {
|
||||||
{
|
|
||||||
// get the "fileas" tags for this post
|
// get the "fileas" tags for this post
|
||||||
$filedas = FileTag::fileToList($categories, 'file');
|
$filedas = FileTag::fileToArray($categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save old and new categories, so we can determine what needs to be deleted from pconfig
|
// save old and new categories, so we can determine what needs to be deleted from pconfig
|
||||||
|
@ -338,10 +338,9 @@ function item_post(App $a) {
|
||||||
$categories = FileTag::listToFile(trim(defaults($_REQUEST, 'category', '')), 'category');
|
$categories = FileTag::listToFile(trim(defaults($_REQUEST, 'category', '')), 'category');
|
||||||
$categories_new = $categories;
|
$categories_new = $categories;
|
||||||
|
|
||||||
if (!empty($filedas))
|
if (!empty($filedas) && is_array($filedas)) {
|
||||||
{
|
|
||||||
// append the fileas stuff to the new categories list
|
// append the fileas stuff to the new categories list
|
||||||
$categories .= FileTag::listToFile($filedas, 'file');
|
$categories .= FileTag::arrayToFile($filedas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get contact info for poster
|
// get contact info for poster
|
||||||
|
@ -605,8 +604,6 @@ function item_post(App $a) {
|
||||||
$origin = $_REQUEST['origin'];
|
$origin = $_REQUEST['origin'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$notify_type = ($toplevel_item_id ? 'comment-new' : 'wall-new');
|
|
||||||
|
|
||||||
$uri = ($message_id ? $message_id : Item::newURI($api_source ? $profile_uid : $uid, $guid));
|
$uri = ($message_id ? $message_id : Item::newURI($api_source ? $profile_uid : $uid, $guid));
|
||||||
|
|
||||||
// Fallback so that we alway have a parent uri
|
// Fallback so that we alway have a parent uri
|
||||||
|
@ -871,7 +868,7 @@ function item_post(App $a) {
|
||||||
// When we are doing some forum posting via ! we have to start the notifier manually.
|
// When we are doing some forum posting via ! we have to start the notifier manually.
|
||||||
// These kind of posts don't initiate the notifier call in the item class.
|
// These kind of posts don't initiate the notifier call in the item class.
|
||||||
if ($only_to_forum) {
|
if ($only_to_forum) {
|
||||||
Worker::add(PRIORITY_HIGH, "Notifier", $notify_type, $post_id);
|
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::POST, $post_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::log('post_complete');
|
Logger::log('post_complete');
|
||||||
|
|
|
@ -78,9 +78,7 @@ function network_init(App $a)
|
||||||
|
|
||||||
// convert query string to array. remove friendica args
|
// convert query string to array. remove friendica args
|
||||||
$query_array = [];
|
$query_array = [];
|
||||||
$query_string = str_replace($a->cmd . '?', '', $a->query_string);
|
parse_str(parse_url($a->query_string, PHP_URL_QUERY), $query_array);
|
||||||
parse_str($query_string, $query_array);
|
|
||||||
array_shift($query_array);
|
|
||||||
|
|
||||||
// fetch last used network view and redirect if needed
|
// fetch last used network view and redirect if needed
|
||||||
if (!$is_a_date_query) {
|
if (!$is_a_date_query) {
|
||||||
|
@ -100,7 +98,7 @@ function network_init(App $a)
|
||||||
|
|
||||||
if ($remember_tab) {
|
if ($remember_tab) {
|
||||||
// redirect if current selected tab is '/network' and
|
// redirect if current selected tab is '/network' and
|
||||||
// last selected tab is _not_ '/network?f=&order=comment'.
|
// last selected tab is _not_ '/network?order=comment'.
|
||||||
// and this isn't a date query
|
// and this isn't a date query
|
||||||
|
|
||||||
$tab_baseurls = [
|
$tab_baseurls = [
|
||||||
|
@ -112,12 +110,12 @@ function network_init(App $a)
|
||||||
'', //bookmarked
|
'', //bookmarked
|
||||||
];
|
];
|
||||||
$tab_args = [
|
$tab_args = [
|
||||||
'f=&order=comment', //all
|
'order=comment', //all
|
||||||
'f=&order=post', //postord
|
'order=post', //postord
|
||||||
'f=&conv=1', //conv
|
'conv=1', //conv
|
||||||
'', //new
|
'', //new
|
||||||
'f=&star=1', //starred
|
'star=1', //starred
|
||||||
'f=&bmark=1', //bookmarked
|
'bmark=1', //bookmarked
|
||||||
];
|
];
|
||||||
|
|
||||||
$k = array_search('active', $last_sel_tabs);
|
$k = array_search('active', $last_sel_tabs);
|
||||||
|
@ -141,7 +139,7 @@ function network_init(App $a)
|
||||||
|
|
||||||
if ($remember_tab) {
|
if ($remember_tab) {
|
||||||
$net_args = array_merge($query_array, $net_args);
|
$net_args = array_merge($query_array, $net_args);
|
||||||
$net_queries = build_querystring($net_args);
|
$net_queries = http_build_query($net_args);
|
||||||
|
|
||||||
$redir_url = ($net_queries ? $net_baseurl . '?' . $net_queries : $net_baseurl);
|
$redir_url = ($net_queries ? $net_baseurl . '?' . $net_queries : $net_baseurl);
|
||||||
|
|
||||||
|
@ -155,7 +153,7 @@ function network_init(App $a)
|
||||||
|
|
||||||
$a->page['aside'] .= Group::sidebarWidget('network/0', 'network', 'standard', $group_id);
|
$a->page['aside'] .= Group::sidebarWidget('network/0', 'network', 'standard', $group_id);
|
||||||
$a->page['aside'] .= ForumManager::widget(local_user(), $cid);
|
$a->page['aside'] .= ForumManager::widget(local_user(), $cid);
|
||||||
$a->page['aside'] .= posted_date_widget('network', local_user(), false);
|
$a->page['aside'] .= Widget::postedByYear('network', local_user(), false);
|
||||||
$a->page['aside'] .= Widget::networks('network', defaults($_GET, 'nets', '') );
|
$a->page['aside'] .= Widget::networks('network', defaults($_GET, 'nets', '') );
|
||||||
$a->page['aside'] .= saved_searches($search);
|
$a->page['aside'] .= saved_searches($search);
|
||||||
$a->page['aside'] .= Widget::fileAs('network', defaults($_GET, 'file', '') );
|
$a->page['aside'] .= Widget::fileAs('network', defaults($_GET, 'file', '') );
|
||||||
|
@ -203,12 +201,12 @@ function saved_searches($search)
|
||||||
*
|
*
|
||||||
* urls -> returns
|
* urls -> returns
|
||||||
* '/network' => $no_active = 'active'
|
* '/network' => $no_active = 'active'
|
||||||
* '/network?f=&order=comment' => $comment_active = 'active'
|
* '/network?order=comment' => $comment_active = 'active'
|
||||||
* '/network?f=&order=post' => $postord_active = 'active'
|
* '/network?order=post' => $postord_active = 'active'
|
||||||
* '/network?f=&conv=1', => $conv_active = 'active'
|
* '/network?conv=1', => $conv_active = 'active'
|
||||||
* '/network/new', => $new_active = 'active'
|
* '/network/new', => $new_active = 'active'
|
||||||
* '/network?f=&star=1', => $starred_active = 'active'
|
* '/network?star=1', => $starred_active = 'active'
|
||||||
* '/network?f=&bmark=1', => $bookmarked_active = 'active'
|
* '/network?bmark=1', => $bookmarked_active = 'active'
|
||||||
*
|
*
|
||||||
* @param App $a
|
* @param App $a
|
||||||
* @return array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active);
|
* @return array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active);
|
||||||
|
@ -974,7 +972,7 @@ function network_tabs(App $a)
|
||||||
$tabs = [
|
$tabs = [
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Commented Order'),
|
'label' => L10n::t('Commented Order'),
|
||||||
'url' => str_replace('/new', '', $cmd) . '?f=&order=comment' . (!empty($_GET['cid']) ? '&cid=' . $_GET['cid'] : ''),
|
'url' => str_replace('/new', '', $cmd) . '?order=comment' . (!empty($_GET['cid']) ? '&cid=' . $_GET['cid'] : ''),
|
||||||
'sel' => $all_active,
|
'sel' => $all_active,
|
||||||
'title' => L10n::t('Sort by Comment Date'),
|
'title' => L10n::t('Sort by Comment Date'),
|
||||||
'id' => 'commented-order-tab',
|
'id' => 'commented-order-tab',
|
||||||
|
@ -982,7 +980,7 @@ function network_tabs(App $a)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Posted Order'),
|
'label' => L10n::t('Posted Order'),
|
||||||
'url' => str_replace('/new', '', $cmd) . '?f=&order=post' . (!empty($_GET['cid']) ? '&cid=' . $_GET['cid'] : ''),
|
'url' => str_replace('/new', '', $cmd) . '?order=post' . (!empty($_GET['cid']) ? '&cid=' . $_GET['cid'] : ''),
|
||||||
'sel' => $postord_active,
|
'sel' => $postord_active,
|
||||||
'title' => L10n::t('Sort by Post Date'),
|
'title' => L10n::t('Sort by Post Date'),
|
||||||
'id' => 'posted-order-tab',
|
'id' => 'posted-order-tab',
|
||||||
|
@ -992,7 +990,7 @@ function network_tabs(App $a)
|
||||||
|
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Personal'),
|
'label' => L10n::t('Personal'),
|
||||||
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
|
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
|
||||||
'sel' => $conv_active,
|
'sel' => $conv_active,
|
||||||
'title' => L10n::t('Posts that mention or involve you'),
|
'title' => L10n::t('Posts that mention or involve you'),
|
||||||
'id' => 'personal-tab',
|
'id' => 'personal-tab',
|
||||||
|
@ -1002,7 +1000,7 @@ function network_tabs(App $a)
|
||||||
if (Feature::isEnabled(local_user(), 'new_tab')) {
|
if (Feature::isEnabled(local_user(), 'new_tab')) {
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('New'),
|
'label' => L10n::t('New'),
|
||||||
'url' => 'network/new' . (!empty($_GET['cid']) ? '/?f=&cid=' . $_GET['cid'] : ''),
|
'url' => 'network/new' . (!empty($_GET['cid']) ? '/?cid=' . $_GET['cid'] : ''),
|
||||||
'sel' => $new_active,
|
'sel' => $new_active,
|
||||||
'title' => L10n::t('Activity Stream - by date'),
|
'title' => L10n::t('Activity Stream - by date'),
|
||||||
'id' => 'activitiy-by-date-tab',
|
'id' => 'activitiy-by-date-tab',
|
||||||
|
@ -1013,7 +1011,7 @@ function network_tabs(App $a)
|
||||||
if (Feature::isEnabled(local_user(), 'link_tab')) {
|
if (Feature::isEnabled(local_user(), 'link_tab')) {
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Shared Links'),
|
'label' => L10n::t('Shared Links'),
|
||||||
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
|
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
|
||||||
'sel' => $bookmarked_active,
|
'sel' => $bookmarked_active,
|
||||||
'title' => L10n::t('Interesting Links'),
|
'title' => L10n::t('Interesting Links'),
|
||||||
'id' => 'shared-links-tab',
|
'id' => 'shared-links-tab',
|
||||||
|
@ -1023,7 +1021,7 @@ function network_tabs(App $a)
|
||||||
|
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Starred'),
|
'label' => L10n::t('Starred'),
|
||||||
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&star=1',
|
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?cid=' . $_GET['cid'] : '/?f=') . '&star=1',
|
||||||
'sel' => $starred_active,
|
'sel' => $starred_active,
|
||||||
'title' => L10n::t('Favourite Posts'),
|
'title' => L10n::t('Favourite Posts'),
|
||||||
'id' => 'starred-posts-tab',
|
'id' => 'starred-posts-tab',
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @file mod/newmember.php
|
|
||||||
*/
|
|
||||||
use Friendica\App;
|
|
||||||
use Friendica\Core\Config;
|
|
||||||
use Friendica\Core\L10n;
|
|
||||||
|
|
||||||
function newmember_content(App $a)
|
|
||||||
{
|
|
||||||
$o = '<div class="generic-page-wrapper">';
|
|
||||||
$o .= '<h1>' . L10n::t('Welcome to Friendica') . '</h1>';
|
|
||||||
$o .= '<h3>' . L10n::t('New Member Checklist') . '</h3>';
|
|
||||||
$o .= '<div style="font-size: 120%;">';
|
|
||||||
$o .= L10n::t('We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page. A link to this page will be visible from your home page for two weeks after your initial registration and then will quietly disappear.');
|
|
||||||
$o .= '<h4>' . L10n::t('Getting Started') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
$o .= '<li> ' . '<a target="newmember" href="help/Quick-Start-guide">' . L10n::t('Friendica Walk-Through') . '</a><br />' . L10n::t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL;
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '<h4>' . L10n::t('Settings') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="settings">' . L10n::t('Go to Your Settings') . '</a><br />' . L10n::t('On your <em>Settings</em> page - change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.') . '</li>' . EOL;
|
|
||||||
$o .= '<li>' . L10n::t('Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you.') . '</li>' . EOL;
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '<h4>' . L10n::t('Profile') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="profile_photo">' . L10n::t('Upload Profile Photo') . '</a><br />' . L10n::t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.') . '</li>' . EOL;
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="profiles">' . L10n::t('Edit Your Profile') . '</a><br />' . L10n::t('Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.') . '</li>' . EOL;
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="profiles">' . L10n::t('Profile Keywords') . '</a><br />' . L10n::t('Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships.') . '</li>' . EOL;
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '<h4>' . L10n::t('Connecting') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
|
|
||||||
$mail_disabled = ((function_exists('imap_open') && (!Config::get('system', 'imap_disabled'))) ? 0 : 1);
|
|
||||||
|
|
||||||
if (!$mail_disabled) {
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="settings/connectors">' . L10n::t('Importing Emails') . '</a><br />' . L10n::t('Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX') . '</li>' . EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="contact">' . L10n::t('Go to Your Contacts Page') . '</a><br />' . L10n::t('Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Add New Contact</em> dialog.') . '</li>' . EOL;
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="directory">' . L10n::t("Go to Your Site's Directory") . '</a><br />' . L10n::t('The Directory page lets you find other people in this network or other federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on their profile page. Provide your own Identity Address if requested.') . '</li>' . EOL;
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="contact">' . L10n::t('Finding New People') . '</a><br />' . L10n::t("On the side panel of the Contacts page are several tools to find new friends. We can match people by interest, look up people by name or interest, and provide suggestions based on network relationships. On a brand new site, friend suggestions will usually begin to be populated within 24 hours.") . '</li>' . EOL;
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '<h4>' . L10n::t('Groups') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="contact">' . L10n::t('Group Your Contacts') . '</a><br />' . L10n::t('Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page.') . '</li>' . EOL;
|
|
||||||
|
|
||||||
if (Config::get('system', 'newuser_private')) {
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="help/Groups-and-Privacy">' . L10n::t("Why Aren't My Posts Public?") . '</a><br />' . L10n::t("Friendica respects your privacy. By default, your posts will only show up to people you've added as friends. For more information, see the help section from the link above.") . '</li>' . EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '<h4>' . L10n::t('Getting Help') . '</h4>';
|
|
||||||
$o .= '<ul>';
|
|
||||||
$o .= '<li>' . '<a target="newmember" href="help">' . L10n::t('Go to the Help Section') . '</a><br />' . L10n::t('Our <strong>help</strong> pages may be consulted for detail on other program features and resources.') . '</li>' . EOL;
|
|
||||||
$o .= '</ul>';
|
|
||||||
$o .= '</div>';
|
|
||||||
$o .= '</div>';
|
|
||||||
|
|
||||||
return $o;
|
|
||||||
}
|
|
|
@ -28,7 +28,7 @@ function notes_content(App $a, $update = false)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$o = Profile::getTabs($a, true);
|
$o = Profile::getTabs($a, 'notes', true);
|
||||||
|
|
||||||
if (!$update) {
|
if (!$update) {
|
||||||
$o .= '<h3>' . L10n::t('Personal Notes') . '</h3>';
|
$o .= '<h3>' . L10n::t('Personal Notes') . '</h3>';
|
||||||
|
|
|
@ -121,6 +121,9 @@ function notifications_content(App $a)
|
||||||
} elseif (($a->argc > 1) && ($a->argv[1] == 'home')) {
|
} elseif (($a->argc > 1) && ($a->argv[1] == 'home')) {
|
||||||
$notif_header = L10n::t('Home Notifications');
|
$notif_header = L10n::t('Home Notifications');
|
||||||
$notifs = $nm->homeNotifs($show, $startrec, $perpage);
|
$notifs = $nm->homeNotifs($show, $startrec, $perpage);
|
||||||
|
// fallback - redirect to main page
|
||||||
|
} else {
|
||||||
|
$a->internalRedirect('notifications');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the pager
|
// Set the pager
|
||||||
|
|
|
@ -9,12 +9,14 @@
|
||||||
*
|
*
|
||||||
* @see ParseUrl::getSiteinfo() for more information about scraping embeddable content
|
* @see ParseUrl::getSiteinfo() for more information about scraping embeddable content
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\ParseUrl;
|
use Friendica\Util\ParseUrl;
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
function parse_url_content(App $a)
|
function parse_url_content(App $a)
|
||||||
{
|
{
|
||||||
|
@ -25,10 +27,14 @@ function parse_url_content(App $a)
|
||||||
|
|
||||||
$br = "\n";
|
$br = "\n";
|
||||||
|
|
||||||
if (!empty($_GET['binurl'])) {
|
if (!empty($_GET['binurl']) && Strings::isHex($_GET['binurl'])) {
|
||||||
$url = trim(hex2bin($_GET['binurl']));
|
$url = trim(hex2bin($_GET['binurl']));
|
||||||
} else {
|
} elseif (!empty($_GET['url'])) {
|
||||||
$url = trim($_GET['url']);
|
$url = trim($_GET['url']);
|
||||||
|
// fallback in case no url is valid
|
||||||
|
} else {
|
||||||
|
Logger::info('No url given');
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_GET['title'])) {
|
if (!empty($_GET['title'])) {
|
||||||
|
@ -64,9 +70,8 @@ function parse_url_content(App $a)
|
||||||
|
|
||||||
// Check if the URL is an image, video or audio file. If so format
|
// Check if the URL is an image, video or audio file. If so format
|
||||||
// the URL with the corresponding BBCode media tag
|
// the URL with the corresponding BBCode media tag
|
||||||
$redirects = 0;
|
|
||||||
// Fetch the header of the URL
|
// Fetch the header of the URL
|
||||||
$curlResponse = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]);
|
$curlResponse = Network::curl($url, false, ['novalidate' => true, 'nobody' => true]);
|
||||||
|
|
||||||
if ($curlResponse->isSuccess()) {
|
if ($curlResponse->isSuccess()) {
|
||||||
// Convert the header fields into an array
|
// Convert the header fields into an array
|
||||||
|
|
|
@ -29,8 +29,8 @@ use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Map;
|
use Friendica\Util\Map;
|
||||||
use Friendica\Util\Security;
|
use Friendica\Util\Security;
|
||||||
use Friendica\Util\Temporal;
|
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Util\Temporal;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
function photos_init(App $a) {
|
function photos_init(App $a) {
|
||||||
|
@ -188,6 +188,9 @@ function photos_post(App $a)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($a->argc > 3 && $a->argv[2] === 'album') {
|
if ($a->argc > 3 && $a->argv[2] === 'album') {
|
||||||
|
if (!Strings::isHex($a->argv[3])) {
|
||||||
|
$a->internalRedirect('photos/' . $a->data['user']['nickname'] . '/album');
|
||||||
|
}
|
||||||
$album = hex2bin($a->argv[3]);
|
$album = hex2bin($a->argv[3]);
|
||||||
|
|
||||||
if ($album === L10n::t('Profile Photos') || $album === 'Contact Photos' || $album === L10n::t('Contact Photos')) {
|
if ($album === L10n::t('Profile Photos') || $album === 'Contact Photos' || $album === L10n::t('Contact Photos')) {
|
||||||
|
@ -315,7 +318,7 @@ function photos_post(App $a)
|
||||||
$str_group_deny = !empty($_POST['group_deny']) ? perms2str($_POST['group_deny']) : '';
|
$str_group_deny = !empty($_POST['group_deny']) ? perms2str($_POST['group_deny']) : '';
|
||||||
$str_contact_deny = !empty($_POST['contact_deny']) ? perms2str($_POST['contact_deny']) : '';
|
$str_contact_deny = !empty($_POST['contact_deny']) ? perms2str($_POST['contact_deny']) : '';
|
||||||
|
|
||||||
$resource_id = $a->argv[2];
|
$resource_id = $a->argv[3];
|
||||||
|
|
||||||
if (!strlen($albname)) {
|
if (!strlen($albname)) {
|
||||||
$albname = DateTimeFormat::localNow('Y');
|
$albname = DateTimeFormat::localNow('Y');
|
||||||
|
@ -418,10 +421,11 @@ function photos_post(App $a)
|
||||||
|
|
||||||
if ($item_id) {
|
if ($item_id) {
|
||||||
$item = Item::selectFirst(['tag', 'inform'], ['id' => $item_id, 'uid' => $page_owner_uid]);
|
$item = Item::selectFirst(['tag', 'inform'], ['id' => $item_id, 'uid' => $page_owner_uid]);
|
||||||
}
|
|
||||||
if (DBA::isResult($item)) {
|
if (DBA::isResult($item)) {
|
||||||
$old_tag = $item['tag'];
|
$old_tag = $item['tag'];
|
||||||
$old_inform = $item['inform'];
|
$old_inform = $item['inform'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($rawtags)) {
|
if (strlen($rawtags)) {
|
||||||
|
@ -524,13 +528,13 @@ function photos_post(App $a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$newtag = $old_tag;
|
$newtag = $old_tag ?? '';
|
||||||
if (strlen($newtag) && strlen($str_tags)) {
|
if (strlen($newtag) && strlen($str_tags)) {
|
||||||
$newtag .= ',';
|
$newtag .= ',';
|
||||||
}
|
}
|
||||||
$newtag .= $str_tags;
|
$newtag .= $str_tags;
|
||||||
|
|
||||||
$newinform = $old_inform;
|
$newinform = $old_inform ?? '';
|
||||||
if (strlen($newinform) && strlen($inform)) {
|
if (strlen($newinform) && strlen($inform)) {
|
||||||
$newinform .= ',';
|
$newinform .= ',';
|
||||||
}
|
}
|
||||||
|
@ -735,7 +739,7 @@ function photos_post(App $a)
|
||||||
@unlink($src);
|
@unlink($src);
|
||||||
$foo = 0;
|
$foo = 0;
|
||||||
Hook::callAll('photo_post_end',$foo);
|
Hook::callAll('photo_post_end',$foo);
|
||||||
exit();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$exif = $image->orient($src);
|
$exif = $image->orient($src);
|
||||||
|
@ -761,7 +765,7 @@ function photos_post(App $a)
|
||||||
if (!$r) {
|
if (!$r) {
|
||||||
Logger::log('mod/photos.php: photos_post(): image store failed', Logger::DEBUG);
|
Logger::log('mod/photos.php: photos_post(): image store failed', Logger::DEBUG);
|
||||||
notice(L10n::t('Image upload failed.') . EOL);
|
notice(L10n::t('Image upload failed.') . EOL);
|
||||||
exit();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($width > 640 || $height > 640) {
|
if ($width > 640 || $height > 640) {
|
||||||
|
@ -950,7 +954,7 @@ function photos_content(App $a)
|
||||||
|
|
||||||
// tabs
|
// tabs
|
||||||
$is_owner = (local_user() && (local_user() == $owner_uid));
|
$is_owner = (local_user() && (local_user() == $owner_uid));
|
||||||
$o .= Profile::getTabs($a, $is_owner, $a->data['user']['nickname']);
|
$o .= Profile::getTabs($a, 'photos', $is_owner, $a->data['user']['nickname']);
|
||||||
|
|
||||||
// Display upload form
|
// Display upload form
|
||||||
if ($datatype === 'upload') {
|
if ($datatype === 'upload') {
|
||||||
|
@ -959,7 +963,7 @@ function photos_content(App $a)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$selname = $datum ? hex2bin($datum) : '';
|
$selname = Strings::isHex($datum) ? hex2bin($datum) : '';
|
||||||
|
|
||||||
$albumselect = '';
|
$albumselect = '';
|
||||||
|
|
||||||
|
@ -1026,6 +1030,10 @@ function photos_content(App $a)
|
||||||
|
|
||||||
// Display a single photo album
|
// Display a single photo album
|
||||||
if ($datatype === 'album') {
|
if ($datatype === 'album') {
|
||||||
|
// if $datum is not a valid hex, redirect to the default page
|
||||||
|
if (!Strings::isHex($datum)) {
|
||||||
|
$a->internalRedirect('photos/' . $a->data['user']['nickname']. '/album');
|
||||||
|
}
|
||||||
$album = hex2bin($datum);
|
$album = hex2bin($datum);
|
||||||
|
|
||||||
$total = 0;
|
$total = 0;
|
||||||
|
@ -1503,7 +1511,7 @@ function photos_content(App $a)
|
||||||
'$title' => $title_e,
|
'$title' => $title_e,
|
||||||
'$body' => $body_e,
|
'$body' => $body_e,
|
||||||
'$ago' => Temporal::getRelativeDate($item['created']),
|
'$ago' => Temporal::getRelativeDate($item['created']),
|
||||||
'$indent' => (($item['parent'] != $item['item_id']) ? ' comment' : ''),
|
'$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''),
|
||||||
'$drop' => $drop,
|
'$drop' => $drop,
|
||||||
'$comment' => $comment
|
'$comment' => $comment
|
||||||
]);
|
]);
|
||||||
|
@ -1512,7 +1520,7 @@ function photos_content(App $a)
|
||||||
$comments .= Renderer::replaceMacros($cmnt_tpl, [
|
$comments .= Renderer::replaceMacros($cmnt_tpl, [
|
||||||
'$return_path' => '',
|
'$return_path' => '',
|
||||||
'$jsreload' => $return_path,
|
'$jsreload' => $return_path,
|
||||||
'$id' => $item['item_id'],
|
'$id' => $item['id'],
|
||||||
'$parent' => $item['parent'],
|
'$parent' => $item['parent'],
|
||||||
'$profile_uid' => $owner_uid,
|
'$profile_uid' => $owner_uid,
|
||||||
'$mylink' => $contact['url'],
|
'$mylink' => $contact['url'],
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Core\L10n;
|
use Friendica\Core\L10n;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
use Friendica\Core\Session;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Util\Strings;
|
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
function redir_init(App $a) {
|
function redir_init(App $a) {
|
||||||
|
|
||||||
|
@ -70,7 +71,9 @@ function redir_init(App $a) {
|
||||||
&& is_array($_SESSION['remote']))
|
&& is_array($_SESSION['remote']))
|
||||||
{
|
{
|
||||||
foreach ($_SESSION['remote'] as $v) {
|
foreach ($_SESSION['remote'] as $v) {
|
||||||
if ($v['uid'] == $_SESSION['visitor_visiting'] && $v['cid'] == $_SESSION['visitor_id']) {
|
if (!empty($v['uid']) && !empty($v['cid']) &&
|
||||||
|
$v['uid'] == Session::get('visitor_visiting') &&
|
||||||
|
$v['cid'] == Session::get('visitor_id')) {
|
||||||
// Remote user is already authenticated.
|
// Remote user is already authenticated.
|
||||||
$target_url = defaults($url, $contact_url);
|
$target_url = defaults($url, $contact_url);
|
||||||
Logger::log($contact['name'] . " is already authenticated. Redirecting to " . $target_url, Logger::DEBUG);
|
Logger::log($contact['name'] . " is already authenticated. Redirecting to " . $target_url, Logger::DEBUG);
|
||||||
|
|
|
@ -12,13 +12,11 @@ use Friendica\Core\Config;
|
||||||
use Friendica\Core\L10n;
|
use Friendica\Core\L10n;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\System;
|
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
|
use Friendica\Module\BaseSearchModule;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
require_once 'mod/dirfind.php';
|
|
||||||
|
|
||||||
function search_saved_searches() {
|
function search_saved_searches() {
|
||||||
|
|
||||||
$o = '';
|
$o = '';
|
||||||
|
@ -150,10 +148,10 @@ function search_content(App $a) {
|
||||||
$search = substr($search,1);
|
$search = substr($search,1);
|
||||||
}
|
}
|
||||||
if (strpos($search,'@') === 0) {
|
if (strpos($search,'@') === 0) {
|
||||||
return dirfind_content($a);
|
return BaseSearchModule::performSearch();
|
||||||
}
|
}
|
||||||
if (strpos($search,'!') === 0) {
|
if (strpos($search,'!') === 0) {
|
||||||
return dirfind_content($a);
|
return BaseSearchModule::performSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_GET['search-option']))
|
if (!empty($_GET['search-option']))
|
||||||
|
@ -164,11 +162,9 @@ function search_content(App $a) {
|
||||||
$tag = true;
|
$tag = true;
|
||||||
break;
|
break;
|
||||||
case 'contacts':
|
case 'contacts':
|
||||||
return dirfind_content($a, "@");
|
return BaseSearchModule::performSearch('@');
|
||||||
break;
|
|
||||||
case 'forums':
|
case 'forums':
|
||||||
return dirfind_content($a, "!");
|
return BaseSearchModule::performSearch('!');
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$search)
|
if (!$search)
|
||||||
|
|
|
@ -28,6 +28,7 @@ use Friendica\Protocol\Email;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\Temporal;
|
use Friendica\Util\Temporal;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
function get_theme_config_file($theme)
|
function get_theme_config_file($theme)
|
||||||
{
|
{
|
||||||
|
@ -390,7 +391,7 @@ function settings_post(App $a)
|
||||||
BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings');
|
BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings');
|
||||||
|
|
||||||
if (!empty($_POST['resend_relocate'])) {
|
if (!empty($_POST['resend_relocate'])) {
|
||||||
Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user());
|
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, local_user());
|
||||||
info(L10n::t("Relocate message has been send to your contacts"));
|
info(L10n::t("Relocate message has been send to your contacts"));
|
||||||
$a->internalRedirect('settings');
|
$a->internalRedirect('settings');
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
function tagger_content(App $a) {
|
function tagger_content(App $a) {
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ EOT;
|
||||||
|
|
||||||
Hook::callAll('post_local_end', $arr);
|
Hook::callAll('post_local_end', $arr);
|
||||||
|
|
||||||
Worker::add(PRIORITY_HIGH, "Notifier", "tag", $post_id);
|
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::POST, $post_id);
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,27 @@
|
||||||
/**
|
/**
|
||||||
* @file mod/uexport.php
|
* @file mod/uexport.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\L10n;
|
use Friendica\Core\L10n;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Database\DBStructure;
|
||||||
|
|
||||||
function uexport_init(App $a) {
|
function uexport_init(App $a) {
|
||||||
|
/// @todo Don't forget to move this global field as static field in src/Modules
|
||||||
|
global $dbStructure;
|
||||||
|
|
||||||
if (!local_user()) {
|
if (!local_user()) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once("mod/settings.php");
|
require_once("mod/settings.php");
|
||||||
settings_init($a);
|
settings_init($a);
|
||||||
|
|
||||||
|
$dbStructure = DBStructure::definition($a->getBasePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
function uexport_content(App $a) {
|
function uexport_content(App $a) {
|
||||||
|
@ -55,13 +62,25 @@ function uexport_content(App $a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _uexport_multirow($query) {
|
function _uexport_multirow($query) {
|
||||||
|
global $dbStructure;
|
||||||
|
|
||||||
|
preg_match("/\s+from\s+`?([a-z\d_]+)`?/i", $query, $match);
|
||||||
|
$table = $match[1];
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
$r = q($query);
|
$r = q($query);
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
foreach ($r as $rr) {
|
foreach ($r as $rr) {
|
||||||
$p = [];
|
$p = [];
|
||||||
foreach ($rr as $k => $v) {
|
foreach ($rr as $k => $v) {
|
||||||
$p[$k] = $v;
|
switch ($dbStructure[$table]['fields'][$k]['type']) {
|
||||||
|
case 'datetime':
|
||||||
|
$p[$k] = $v ?? DBA::NULL_DATETIME;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$p[$k] = $v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$result[] = $p;
|
$result[] = $p;
|
||||||
}
|
}
|
||||||
|
@ -70,12 +89,25 @@ function _uexport_multirow($query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _uexport_row($query) {
|
function _uexport_row($query) {
|
||||||
|
global $dbStructure;
|
||||||
|
|
||||||
|
preg_match("/\s+from\s+`?([a-z\d_]+)`?/i", $query, $match);
|
||||||
|
$table = $match[1];
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
$r = q($query);
|
$r = q($query);
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
|
|
||||||
foreach ($r as $rr) {
|
foreach ($r as $rr) {
|
||||||
foreach ($rr as $k => $v) {
|
foreach ($rr as $k => $v) {
|
||||||
$result[$k] = $v;
|
switch ($dbStructure[$table]['fields'][$k]['type']) {
|
||||||
|
case 'datetime':
|
||||||
|
$result[$k] = $v ?? DBA::NULL_DATETIME;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result[$k] = $v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ function videos_content(App $a)
|
||||||
|
|
||||||
// tabs
|
// tabs
|
||||||
$_is_owner = (local_user() && (local_user() == $owner_uid));
|
$_is_owner = (local_user() && (local_user() == $owner_uid));
|
||||||
$o .= Profile::getTabs($a, $_is_owner, $a->data['user']['nickname']);
|
$o .= Profile::getTabs($a, 'videos', $_is_owner, $a->data['user']['nickname']);
|
||||||
|
|
||||||
//
|
//
|
||||||
// dispatch request
|
// dispatch request
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @file mod/viewcontacts.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Friendica\App;
|
|
||||||
use Friendica\Content\ContactSelector;
|
|
||||||
use Friendica\Content\Nav;
|
|
||||||
use Friendica\Content\Pager;
|
|
||||||
use Friendica\Core\Config;
|
|
||||||
use Friendica\Core\L10n;
|
|
||||||
use Friendica\Core\Protocol;
|
|
||||||
use Friendica\Core\Renderer;
|
|
||||||
use Friendica\Core\System;
|
|
||||||
use Friendica\Database\DBA;
|
|
||||||
use Friendica\Model\Contact;
|
|
||||||
use Friendica\Model\Profile;
|
|
||||||
use Friendica\Util\Proxy as ProxyUtils;
|
|
||||||
|
|
||||||
function viewcontacts_init(App $a)
|
|
||||||
{
|
|
||||||
if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
|
|
||||||
throw new \Friendica\Network\HTTPException\ForbiddenException(L10n::t('Access denied.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($a->argc < 2) {
|
|
||||||
throw new \Friendica\Network\HTTPException\ForbiddenException(L10n::t('Access denied.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
Nav::setSelected('home');
|
|
||||||
|
|
||||||
$user = DBA::selectFirst('user', [], ['nickname' => $a->argv[1], 'blocked' => false]);
|
|
||||||
if (!DBA::isResult($user)) {
|
|
||||||
throw new \Friendica\Network\HTTPException\NotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$a->data['user'] = $user;
|
|
||||||
$a->profile_uid = $user['uid'];
|
|
||||||
|
|
||||||
Profile::load($a, $a->argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewcontacts_content(App $a)
|
|
||||||
{
|
|
||||||
if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
|
|
||||||
notice(L10n::t('Public access denied.') . EOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$is_owner = $a->profile['profile_uid'] == local_user();
|
|
||||||
|
|
||||||
// tabs
|
|
||||||
$o = Profile::getTabs($a, $is_owner, $a->data['user']['nickname']);
|
|
||||||
|
|
||||||
if (!count($a->profile) || $a->profile['hide-friends']) {
|
|
||||||
notice(L10n::t('Permission denied.') . EOL);
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
||||||
$condition = [
|
|
||||||
'uid' => $a->profile['uid'],
|
|
||||||
'blocked' => false,
|
|
||||||
'pending' => false,
|
|
||||||
'hidden' => false,
|
|
||||||
'archive' => false,
|
|
||||||
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]
|
|
||||||
];
|
|
||||||
|
|
||||||
$total = DBA::count('contact', $condition);
|
|
||||||
|
|
||||||
$pager = new Pager($a->query_string);
|
|
||||||
|
|
||||||
$params = ['order' => ['name' => false], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
|
|
||||||
|
|
||||||
$contacts_stmt = DBA::select('contact', [], $condition, $params);
|
|
||||||
|
|
||||||
if (!DBA::isResult($contacts_stmt)) {
|
|
||||||
info(L10n::t('No contacts.') . EOL);
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
||||||
$contacts = [];
|
|
||||||
|
|
||||||
while ($contact = DBA::fetch($contacts_stmt)) {
|
|
||||||
/// @TODO This triggers an E_NOTICE if 'self' is not there
|
|
||||||
if ($contact['self']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$contact_details = Contact::getDetailsByURL($contact['url'], $a->profile['uid'], $contact);
|
|
||||||
|
|
||||||
$contacts[] = [
|
|
||||||
'id' => $contact['id'],
|
|
||||||
'img_hover' => L10n::t('Visit %s\'s profile [%s]', $contact_details['name'], $contact['url']),
|
|
||||||
'photo_menu' => Contact::photoMenu($contact),
|
|
||||||
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
|
|
||||||
'name' => substr($contact_details['name'], 0, 20),
|
|
||||||
'username' => $contact_details['name'],
|
|
||||||
'details' => $contact_details['location'],
|
|
||||||
'tags' => $contact_details['keywords'],
|
|
||||||
'about' => $contact_details['about'],
|
|
||||||
'account_type' => Contact::getAccountType($contact_details),
|
|
||||||
'url' => Contact::magicLink($contact['url']),
|
|
||||||
'sparkle' => '',
|
|
||||||
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $contact['url']),
|
|
||||||
'network' => ContactSelector::networkToName($contact['network'], $contact['url']),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
DBA::close($contacts_stmt);
|
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate("viewcontact_template.tpl");
|
|
||||||
$o .= Renderer::replaceMacros($tpl, [
|
|
||||||
'$title' => L10n::t('Contacts'),
|
|
||||||
'$contacts' => $contacts,
|
|
||||||
'$paginate' => $pager->renderFull($total),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $o;
|
|
||||||
}
|
|
14
src/App.php
14
src/App.php
|
@ -993,12 +993,6 @@ class App
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr($this->query_string, '.well-known/host-meta') && ($this->query_string != '.well-known/host-meta')) {
|
|
||||||
Module\Special\HTTPException::rawContent(
|
|
||||||
new HTTPException\NotFoundException()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->getMode()->isInstall()) {
|
if (!$this->getMode()->isInstall()) {
|
||||||
// Force SSL redirection
|
// Force SSL redirection
|
||||||
if ($this->baseURL->checkRedirectHttps()) {
|
if ($this->baseURL->checkRedirectHttps()) {
|
||||||
|
@ -1105,7 +1099,7 @@ class App
|
||||||
|
|
||||||
// Compatibility with the Android Diaspora client
|
// Compatibility with the Android Diaspora client
|
||||||
if ($this->module == 'stream') {
|
if ($this->module == 'stream') {
|
||||||
$this->internalRedirect('network?f=&order=post');
|
$this->internalRedirect('network?order=post');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->module == 'conversations') {
|
if ($this->module == 'conversations') {
|
||||||
|
@ -1113,15 +1107,15 @@ class App
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->module == 'commented') {
|
if ($this->module == 'commented') {
|
||||||
$this->internalRedirect('network?f=&order=comment');
|
$this->internalRedirect('network?order=comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->module == 'liked') {
|
if ($this->module == 'liked') {
|
||||||
$this->internalRedirect('network?f=&order=comment');
|
$this->internalRedirect('network?order=comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->module == 'activity') {
|
if ($this->module == 'activity') {
|
||||||
$this->internalRedirect('network/?f=&conv=1');
|
$this->internalRedirect('network?conv=1');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($this->module == 'status_messages') && ($this->cmd == 'status_messages/new')) {
|
if (($this->module == 'status_messages') && ($this->cmd == 'status_messages/new')) {
|
||||||
|
|
|
@ -112,6 +112,7 @@ class Router
|
||||||
$collector->addRoute(['GET'], '/ignored', Module\Contact::class);
|
$collector->addRoute(['GET'], '/ignored', Module\Contact::class);
|
||||||
});
|
});
|
||||||
$this->routeCollector->addRoute(['GET'], '/credits', Module\Credits::class);
|
$this->routeCollector->addRoute(['GET'], '/credits', Module\Credits::class);
|
||||||
|
$this->routeCollector->addRoute(['GET'], '/dirfind', Module\Search\Directory::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/directory', Module\Directory::class);
|
$this->routeCollector->addRoute(['GET'], '/directory', Module\Directory::class);
|
||||||
$this->routeCollector->addGroup('/feed', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/feed', function (RouteCollector $collector) {
|
||||||
$collector->addRoute(['GET'], '/{nickname}', Module\Feed::class);
|
$collector->addRoute(['GET'], '/{nickname}', Module\Feed::class);
|
||||||
|
@ -122,9 +123,9 @@ class Router
|
||||||
});
|
});
|
||||||
$this->routeCollector->addRoute(['GET'], '/feedtest', Module\Debug\Feed::class);
|
$this->routeCollector->addRoute(['GET'], '/feedtest', Module\Debug\Feed::class);
|
||||||
$this->routeCollector->addGroup('/fetch', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/fetch', function (RouteCollector $collector) {
|
||||||
$collector->addRoute(['GET'], '/{guid}/post', Module\Diaspora\Fetch::class);
|
$collector->addRoute(['GET'], '/post/{guid}', Module\Diaspora\Fetch::class);
|
||||||
$collector->addRoute(['GET'], '/{guid}/status_message', Module\Diaspora\Fetch::class);
|
$collector->addRoute(['GET'], '/status_message/{guid}', Module\Diaspora\Fetch::class);
|
||||||
$collector->addRoute(['GET'], '/{guid}/reshare', Module\Diaspora\Fetch::class);
|
$collector->addRoute(['GET'], '/reshare/{guid}', Module\Diaspora\Fetch::class);
|
||||||
});
|
});
|
||||||
$this->routeCollector->addRoute(['GET'], '/filer[/{id:\d+}]', Module\Filer\SaveTag::class);
|
$this->routeCollector->addRoute(['GET'], '/filer[/{id:\d+}]', Module\Filer\SaveTag::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/filerm/{id:\d+}', Module\Filer\RemoveTag::class);
|
$this->routeCollector->addRoute(['GET'], '/filerm/{id:\d+}', Module\Filer\RemoveTag::class);
|
||||||
|
@ -160,6 +161,7 @@ class Router
|
||||||
$this->routeCollector->addRoute(['GET'], '/maintenance', Module\Maintenance::class);
|
$this->routeCollector->addRoute(['GET'], '/maintenance', Module\Maintenance::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/manifest', Module\Manifest::class);
|
$this->routeCollector->addRoute(['GET'], '/manifest', Module\Manifest::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/modexp/{nick}', Module\PublicRSAKey::class);
|
$this->routeCollector->addRoute(['GET'], '/modexp/{nick}', Module\PublicRSAKey::class);
|
||||||
|
$this->routeCollector->addRoute(['GET'], '/newmember', Module\Welcome::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/nodeinfo/1.0', Module\NodeInfo::class);
|
$this->routeCollector->addRoute(['GET'], '/nodeinfo/1.0', Module\NodeInfo::class);
|
||||||
$this->routeCollector->addRoute(['GET'], '/nogroup', Module\Group::class);
|
$this->routeCollector->addRoute(['GET'], '/nogroup', Module\Group::class);
|
||||||
$this->routeCollector->addGroup('/notify', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/notify', function (RouteCollector $collector) {
|
||||||
|
@ -167,7 +169,6 @@ class Router
|
||||||
$collector->addRoute(['GET'], '/view/{id:\d+}', Module\Notifications\Notify::class);
|
$collector->addRoute(['GET'], '/view/{id:\d+}', Module\Notifications\Notify::class);
|
||||||
$collector->addRoute(['GET'], '/mark/all', Module\Notifications\Notify::class);
|
$collector->addRoute(['GET'], '/mark/all', Module\Notifications\Notify::class);
|
||||||
});
|
});
|
||||||
$this->routeCollector->addRoute(['GET'], '/notice/{id:\d+}', Module\GnuSocial\Notice::class);
|
|
||||||
$this->routeCollector->addRoute(['GET'], '/objects/{guid}', Module\Objects::class);
|
$this->routeCollector->addRoute(['GET'], '/objects/{guid}', Module\Objects::class);
|
||||||
$this->routeCollector->addGroup('/oembed', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/oembed', function (RouteCollector $collector) {
|
||||||
$collector->addRoute(['GET'], '/b2h', Module\Oembed::class);
|
$collector->addRoute(['GET'], '/b2h', Module\Oembed::class);
|
||||||
|
@ -186,6 +187,8 @@ class Router
|
||||||
$this->routeCollector->addRoute(['GET'], '/probe', Module\Debug\Probe::class);
|
$this->routeCollector->addRoute(['GET'], '/probe', Module\Debug\Probe::class);
|
||||||
$this->routeCollector->addGroup('/profile', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/profile', function (RouteCollector $collector) {
|
||||||
$collector->addRoute(['GET'], '/{nickname}', Module\Profile::class);
|
$collector->addRoute(['GET'], '/{nickname}', Module\Profile::class);
|
||||||
|
$collector->addRoute(['GET'], '/{nickname}/{to:\d{4}-\d{2}-\d{2}}/{from:\d{4}-\d{2}-\d{2}}', Module\Profile::class);
|
||||||
|
$collector->addRoute(['GET'], '/{nickname}/contacts[/{type}]', Module\Profile\Contacts::class);
|
||||||
$collector->addRoute(['GET'], '/{profile:\d+}/view', Module\Profile::class);
|
$collector->addRoute(['GET'], '/{profile:\d+}/view', Module\Profile::class);
|
||||||
});
|
});
|
||||||
$this->routeCollector->addGroup('/proxy', function (RouteCollector $collector) {
|
$this->routeCollector->addGroup('/proxy', function (RouteCollector $collector) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ HELP;
|
||||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||||
}
|
}
|
||||||
|
|
||||||
$php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php');
|
$php_path = BaseObject::getApp()->getConfig()->get('config', 'php_path', 'php');
|
||||||
|
|
||||||
if ($this->getOption('v')) {
|
if ($this->getOption('v')) {
|
||||||
$this->out('Directory: src');
|
$this->out('Directory: src');
|
||||||
|
@ -57,6 +57,18 @@ HELP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getOption('v')) {
|
||||||
|
$this->out('Directory: tests');
|
||||||
|
}
|
||||||
|
|
||||||
|
$Iterator = new \RecursiveDirectoryIterator('tests');
|
||||||
|
|
||||||
|
foreach (new \RecursiveIteratorIterator($Iterator) as $file) {
|
||||||
|
if (substr($file, -4) === '.php') {
|
||||||
|
$this->checkFile($php_path, $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->getOption('v')) {
|
if ($this->getOption('v')) {
|
||||||
$this->out('Directory: mod');
|
$this->out('Directory: mod');
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ class ForumManager
|
||||||
$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
|
$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
|
||||||
|
|
||||||
$entry = [
|
$entry = [
|
||||||
'url' => 'network?f=&cid=' . $contact['id'],
|
'url' => 'network?cid=' . $contact['id'],
|
||||||
'external_url' => Contact::magicLink($contact['url']),
|
'external_url' => Contact::magicLink($contact['url']),
|
||||||
'name' => $contact['name'],
|
'name' => $contact['name'],
|
||||||
'cid' => $contact['id'],
|
'cid' => $contact['id'],
|
||||||
|
|
|
@ -149,9 +149,13 @@ class Nav
|
||||||
$nav['usermenu'] = [];
|
$nav['usermenu'] = [];
|
||||||
$userinfo = null;
|
$userinfo = null;
|
||||||
|
|
||||||
if (local_user()) {
|
if (local_user() || remote_user()) {
|
||||||
$nav['logout'] = ['logout', L10n::t('Logout'), '', L10n::t('End this session')];
|
$nav['logout'] = ['logout', L10n::t('Logout'), '', L10n::t('End this session')];
|
||||||
|
} else {
|
||||||
|
$nav['login'] = ['login', L10n::t('Login'), ($a->module == 'login' ? 'selected' : ''), L10n::t('Sign in')];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_user()) {
|
||||||
// user menu
|
// user menu
|
||||||
$nav['usermenu'][] = ['profile/' . $a->user['nickname'], L10n::t('Status'), '', L10n::t('Your posts and conversations')];
|
$nav['usermenu'][] = ['profile/' . $a->user['nickname'], L10n::t('Status'), '', L10n::t('Your posts and conversations')];
|
||||||
$nav['usermenu'][] = ['profile/' . $a->user['nickname'] . '?tab=profile', L10n::t('Profile'), '', L10n::t('Your profile page')];
|
$nav['usermenu'][] = ['profile/' . $a->user['nickname'] . '?tab=profile', L10n::t('Profile'), '', L10n::t('Your profile page')];
|
||||||
|
@ -166,8 +170,6 @@ class Nav
|
||||||
'icon' => (DBA::isResult($contact) ? $a->removeBaseURL($contact['micro']) : 'images/person-48.jpg'),
|
'icon' => (DBA::isResult($contact) ? $a->removeBaseURL($contact['micro']) : 'images/person-48.jpg'),
|
||||||
'name' => $a->user['username'],
|
'name' => $a->user['username'],
|
||||||
];
|
];
|
||||||
} else {
|
|
||||||
$nav['login'] = ['login', L10n::t('Login'), ($a->module == 'login' ? 'selected' : ''), L10n::t('Sign in')];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Home" should also take you home from an authenticated remote profile connection
|
// "Home" should also take you home from an authenticated remote profile connection
|
||||||
|
|
|
@ -83,8 +83,7 @@ class OEmbed
|
||||||
|
|
||||||
if (!in_array($ext, $noexts)) {
|
if (!in_array($ext, $noexts)) {
|
||||||
// try oembed autodiscovery
|
// try oembed autodiscovery
|
||||||
$redirects = 0;
|
$html_text = Network::fetchUrl($embedurl, false, 15, 'text/*');
|
||||||
$html_text = Network::fetchUrl($embedurl, false, $redirects, 15, 'text/*');
|
|
||||||
if ($html_text) {
|
if ($html_text) {
|
||||||
$dom = @DOMDocument::loadHTML($html_text);
|
$dom = @DOMDocument::loadHTML($html_text);
|
||||||
if ($dom) {
|
if ($dom) {
|
||||||
|
|
|
@ -213,7 +213,8 @@ class Smilies
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
$text = preg_replace_callback('/<code>(.*?)<\/code>/ism', 'self::encode', $text);
|
$text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', 'self::encode', $text);
|
||||||
|
$text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', 'self::encode', $text);
|
||||||
|
|
||||||
if ($no_images) {
|
if ($no_images) {
|
||||||
$cleaned = ['texts' => [], 'icons' => []];
|
$cleaned = ['texts' => [], 'icons' => []];
|
||||||
|
@ -230,7 +231,8 @@ class Smilies
|
||||||
$text = preg_replace_callback('/<(3+)/', 'self::pregHeart', $text);
|
$text = preg_replace_callback('/<(3+)/', 'self::pregHeart', $text);
|
||||||
$text = self::strOrigReplace($smilies['texts'], $smilies['icons'], $text);
|
$text = self::strOrigReplace($smilies['texts'], $smilies['icons'], $text);
|
||||||
|
|
||||||
$text = preg_replace_callback('/<code>(.*?)<\/code>/ism', 'self::decode', $text);
|
$text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', 'self::decode', $text);
|
||||||
|
$text = preg_replace_callback('/<(pre)>(.*?)<\/pre>/ism', 'self::decode', $text);
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +244,7 @@ class Smilies
|
||||||
*/
|
*/
|
||||||
private static function encode($m)
|
private static function encode($m)
|
||||||
{
|
{
|
||||||
return '<code>' . Strings::base64UrlEncode($m[1]) . '</code>';
|
return '<' . $m[1] . '>' . Strings::base64UrlEncode($m[2]) . '</' . $m[1] . '>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,7 +255,7 @@ class Smilies
|
||||||
*/
|
*/
|
||||||
private static function decode($m)
|
private static function decode($m)
|
||||||
{
|
{
|
||||||
return '<code>' . Strings::base64UrlDecode($m[1]) . '</code>';
|
return '<' . $m[1] . '>' . Strings::base64UrlDecode($m[2]) . '</' . $m[1] . '>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,7 @@ class BBCode extends BaseObject
|
||||||
|
|
||||||
$attacheddata = $data[2];
|
$attacheddata = $data[2];
|
||||||
|
|
||||||
$URLSearchString = "^\[\]";
|
if (preg_match("/\[img\](.*?)\[\/img\]/ism", $attacheddata, $matches)) {
|
||||||
|
|
||||||
if (preg_match("/\[img\]([$URLSearchString]*)\[\/img\]/ism", $attacheddata, $matches)) {
|
|
||||||
|
|
||||||
$picturedata = Image::getInfoFromURL($matches[1]);
|
$picturedata = Image::getInfoFromURL($matches[1]);
|
||||||
|
|
||||||
|
@ -87,12 +85,12 @@ class BBCode extends BaseObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match("/\[bookmark\=([$URLSearchString]*)\](.*?)\[\/bookmark\]/ism", $attacheddata, $matches)) {
|
if (preg_match("/\[bookmark\=(.*?)\](.*?)\[\/bookmark\]/ism", $attacheddata, $matches)) {
|
||||||
$post["url"] = $matches[1];
|
$post["url"] = $matches[1];
|
||||||
$post["title"] = $matches[2];
|
$post["title"] = $matches[2];
|
||||||
}
|
}
|
||||||
if (!empty($post["url"]) && (in_array($post["type"], ["link", "video"]))
|
if (!empty($post["url"]) && (in_array($post["type"], ["link", "video"]))
|
||||||
&& preg_match("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", $attacheddata, $matches)) {
|
&& preg_match("/\[url\=(.*?)\](.*?)\[\/url\]/ism", $attacheddata, $matches)) {
|
||||||
$post["url"] = $matches[1];
|
$post["url"] = $matches[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,14 +243,18 @@ class BBCode extends BaseObject
|
||||||
// Simplify image codes
|
// Simplify image codes
|
||||||
$body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
|
$body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
|
||||||
|
|
||||||
$URLSearchString = "^\[\]";
|
$body = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", '[img]$1[/img]', $body);
|
||||||
|
|
||||||
$body = preg_replace("/\[img\=([$URLSearchString]*)\](.*?)\[\/img\]/ism", '[img]$1[/img]', $body);
|
if (preg_match_all("(\[url=(.*?)\]\s*\[img\](.*?)\[\/img\]\s*\[\/url\])ism", $body, $pictures, PREG_SET_ORDER)) {
|
||||||
|
|
||||||
if (preg_match_all("(\[url=([$URLSearchString]*)\]\s*\[img\]([$URLSearchString]*)\[\/img\]\s*\[\/url\])ism", $body, $pictures, PREG_SET_ORDER)) {
|
|
||||||
if ((count($pictures) == 1) && !$has_title) {
|
if ((count($pictures) == 1) && !$has_title) {
|
||||||
// Checking, if the link goes to a picture
|
if (!empty($item['object-type']) && ($item['object-type'] == ACTIVITY_OBJ_IMAGE)) {
|
||||||
$data = ParseUrl::getSiteinfoCached($pictures[0][1], true);
|
// Replace the preview picture with the real picture
|
||||||
|
$url = str_replace('-1.', '-0.', $pictures[0][2]);
|
||||||
|
$data = ['url' => $url, 'type' => 'photo'];
|
||||||
|
} else {
|
||||||
|
// Checking, if the link goes to a picture
|
||||||
|
$data = ParseUrl::getSiteinfoCached($pictures[0][1], true);
|
||||||
|
}
|
||||||
|
|
||||||
// Workaround:
|
// Workaround:
|
||||||
// Sometimes photo posts to the own album are not detected at the start.
|
// Sometimes photo posts to the own album are not detected at the start.
|
||||||
|
@ -271,14 +273,14 @@ class BBCode extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
$post["preview"] = $pictures[0][2];
|
$post["preview"] = $pictures[0][2];
|
||||||
$post["text"] = str_replace($pictures[0][0], "", $body);
|
$post["text"] = trim(str_replace($pictures[0][0], "", $body));
|
||||||
} else {
|
} else {
|
||||||
$imgdata = Image::getInfoFromURL($pictures[0][1]);
|
$imgdata = Image::getInfoFromURL($pictures[0][1]);
|
||||||
if ($imgdata && substr($imgdata["mime"], 0, 6) == "image/") {
|
if ($imgdata && substr($imgdata["mime"], 0, 6) == "image/") {
|
||||||
$post["type"] = "photo";
|
$post["type"] = "photo";
|
||||||
$post["image"] = $pictures[0][1];
|
$post["image"] = $pictures[0][1];
|
||||||
$post["preview"] = $pictures[0][2];
|
$post["preview"] = $pictures[0][2];
|
||||||
$post["text"] = str_replace($pictures[0][0], "", $body);
|
$post["text"] = trim(str_replace($pictures[0][0], "", $body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif (count($pictures) > 0) {
|
} elseif (count($pictures) > 0) {
|
||||||
|
@ -287,7 +289,7 @@ class BBCode extends BaseObject
|
||||||
$post["image"] = $pictures[0][2];
|
$post["image"] = $pictures[0][2];
|
||||||
$post["text"] = $body;
|
$post["text"] = $body;
|
||||||
}
|
}
|
||||||
} elseif (preg_match_all("(\[img\]([$URLSearchString]*)\[\/img\])ism", $body, $pictures, PREG_SET_ORDER)) {
|
} elseif (preg_match_all("(\[img\](.*?)\[\/img\])ism", $body, $pictures, PREG_SET_ORDER)) {
|
||||||
if ((count($pictures) == 1) && !$has_title) {
|
if ((count($pictures) == 1) && !$has_title) {
|
||||||
$post["type"] = "photo";
|
$post["type"] = "photo";
|
||||||
$post["image"] = $pictures[0][1];
|
$post["image"] = $pictures[0][1];
|
||||||
|
@ -301,8 +303,8 @@ class BBCode extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for the external links
|
// Test for the external links
|
||||||
preg_match_all("(\[url\]([$URLSearchString]*)\[\/url\])ism", $body, $links1, PREG_SET_ORDER);
|
preg_match_all("(\[url\](.*?)\[\/url\])ism", $body, $links1, PREG_SET_ORDER);
|
||||||
preg_match_all("(\[url\=([$URLSearchString]*)\].*?\[\/url\])ism", $body, $links2, PREG_SET_ORDER);
|
preg_match_all("(\[url\=(.*?)\].*?\[\/url\])ism", $body, $links2, PREG_SET_ORDER);
|
||||||
|
|
||||||
$links = array_merge($links1, $links2);
|
$links = array_merge($links1, $links2);
|
||||||
|
|
||||||
|
@ -563,7 +565,7 @@ class BBCode extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
$return = '';
|
$return = '';
|
||||||
if ($simplehtml == 7) {
|
if (in_array($simplehtml, [7, 9])) {
|
||||||
$return = self::convertUrlForOStatus($data["url"]);
|
$return = self::convertUrlForOStatus($data["url"]);
|
||||||
} elseif (($simplehtml != 4) && ($simplehtml != 0)) {
|
} elseif (($simplehtml != 4) && ($simplehtml != 0)) {
|
||||||
$return = sprintf('<a href="%s" target="_blank">%s</a><br>', $data["url"], $data["title"]);
|
$return = sprintf('<a href="%s" target="_blank">%s</a><br>', $data["url"], $data["title"]);
|
||||||
|
@ -979,16 +981,9 @@ class BBCode extends BaseObject
|
||||||
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n" . $content;
|
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n" . $content;
|
||||||
break;
|
break;
|
||||||
case 7: // statusnet/GNU Social
|
case 7: // statusnet/GNU Social
|
||||||
|
case 9: // ActivityPub
|
||||||
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n";
|
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n";
|
||||||
break;
|
break;
|
||||||
case 9: // Google+
|
|
||||||
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n";
|
|
||||||
$text .= '<p>' . $content . '</p>' . "\n";
|
|
||||||
|
|
||||||
if ($attributes['link'] != '') {
|
|
||||||
$text .= '<p>' . $attributes['link'] . '</p>';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
// Transforms quoted tweets in rich attachments to avoid nested tweets
|
// Transforms quoted tweets in rich attachments to avoid nested tweets
|
||||||
if (stripos(Strings::normaliseLink($attributes['link']), 'http://twitter.com/') === 0 && OEmbed::isAllowedURL($attributes['link'])) {
|
if (stripos(Strings::normaliseLink($attributes['link']), 'http://twitter.com/') === 0 && OEmbed::isAllowedURL($attributes['link'])) {
|
||||||
|
@ -1140,13 +1135,14 @@ class BBCode extends BaseObject
|
||||||
* Simple HTML values meaning:
|
* Simple HTML values meaning:
|
||||||
* - 0: Friendica display
|
* - 0: Friendica display
|
||||||
* - 1: Unused
|
* - 1: Unused
|
||||||
* - 2: Used for Google+, Windows Phone push, Friendica API
|
* - 2: Used for Windows Phone push, Friendica API
|
||||||
* - 3: Used before converting to Markdown in bb2diaspora.php
|
* - 3: Used before converting to Markdown in bb2diaspora.php
|
||||||
* - 4: Used for WordPress, Libertree (before Markdown), pump.io and tumblr
|
* - 4: Used for WordPress, Libertree (before Markdown), pump.io and tumblr
|
||||||
* - 5: Unused
|
* - 5: Unused
|
||||||
* - 6: Unused
|
* - 6: Unused
|
||||||
* - 7: Used for dfrn, OStatus
|
* - 7: Used for dfrn, OStatus
|
||||||
* - 8: Used for WP backlink text setting
|
* - 8: Used for WP backlink text setting
|
||||||
|
* - 9: ActivityPub
|
||||||
*
|
*
|
||||||
* @param string $text
|
* @param string $text
|
||||||
* @param bool $try_oembed
|
* @param bool $try_oembed
|
||||||
|
@ -1250,6 +1246,25 @@ class BBCode extends BaseObject
|
||||||
$text = trim($text);
|
$text = trim($text);
|
||||||
$text = str_replace("\r\n", "\n", $text);
|
$text = str_replace("\r\n", "\n", $text);
|
||||||
|
|
||||||
|
// Remove linefeeds inside of the table elements. See issue #6799
|
||||||
|
$search = ["\n[th]", "[th]\n", " [th]", "\n[/th]", "[/th]\n", "[/th] ",
|
||||||
|
"\n[td]", "[td]\n", " [td]", "\n[/td]", "[/td]\n", "[/td] ",
|
||||||
|
"\n[tr]", "[tr]\n", " [tr]", "[tr] ", "\n[/tr]", "[/tr]\n", " [/tr]", "[/tr] ",
|
||||||
|
"[table]\n", "[table] ", " [table]", "\n[/table]", " [/table]", "[/table] "];
|
||||||
|
$replace = ["[th]", "[th]", "[th]", "[/th]", "[/th]", "[/th]",
|
||||||
|
"[td]", "[td]", "[td]", "[/td]", "[/td]", "[/td]",
|
||||||
|
"[tr]", "[tr]", "[tr]", "[tr]", "[/tr]", "[/tr]", "[/tr]", "[/tr]",
|
||||||
|
"[table]", "[table]", "[table]", "[/table]", "[/table]", "[/table]"];
|
||||||
|
do {
|
||||||
|
$oldtext = $text;
|
||||||
|
$text = str_replace($search, $replace, $text);
|
||||||
|
} while ($oldtext != $text);
|
||||||
|
|
||||||
|
// Replace these here only once
|
||||||
|
$search = ["\n[table]", "[/table]\n"];
|
||||||
|
$replace = ["[table]", "[/table]"];
|
||||||
|
$text = str_replace($search, $replace, $text);
|
||||||
|
|
||||||
// removing multiplicated newlines
|
// removing multiplicated newlines
|
||||||
if (Config::get("system", "remove_multiplicated_lines")) {
|
if (Config::get("system", "remove_multiplicated_lines")) {
|
||||||
$search = ["\n\n\n", "\n ", " \n", "[/quote]\n\n", "\n[/quote]", "[/li]\n", "\n[li]", "\n[ul]", "[/ul]\n", "\n\n[share ", "[/attachment]\n",
|
$search = ["\n\n\n", "\n ", " \n", "[/quote]\n\n", "\n[/quote]", "[/li]\n", "\n[li]", "\n[ul]", "[/ul]\n", "\n\n[share ", "[/attachment]\n",
|
||||||
|
@ -1262,131 +1277,11 @@ class BBCode extends BaseObject
|
||||||
} while ($oldtext != $text);
|
} while ($oldtext != $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the parameters for a URL search string
|
|
||||||
$URLSearchString = "^\[\]";
|
|
||||||
// Set up the parameters for a MAIL search string
|
|
||||||
$MAILSearchString = $URLSearchString;
|
|
||||||
|
|
||||||
// Handle attached links or videos
|
// Handle attached links or videos
|
||||||
$text = self::convertAttachment($text, $simple_html, $try_oembed);
|
$text = self::convertAttachment($text, $simple_html, $try_oembed);
|
||||||
|
|
||||||
// if the HTML is used to generate plain text, then don't do this search, but replace all URL of that kind to text
|
|
||||||
if (!$for_plaintext) {
|
|
||||||
$text = preg_replace(Strings::autoLinkRegEx(), '[url]$1[/url]', $text);
|
|
||||||
if ($simple_html == 7) {
|
|
||||||
$text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
|
|
||||||
$text = preg_replace_callback("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$text = preg_replace("(\[url\]([$URLSearchString]*)\[\/url\])ism", " $1 ", $text);
|
|
||||||
$text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::removePictureLinksCallback', $text);
|
|
||||||
}
|
|
||||||
|
|
||||||
$text = str_replace(["\r","\n"], ['<br />', '<br />'], $text);
|
|
||||||
|
|
||||||
// Remove all hashtag addresses
|
|
||||||
if ((!$try_oembed || $simple_html) && !in_array($simple_html, [3, 7])) {
|
|
||||||
$text = preg_replace("/([#@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$1$3', $text);
|
|
||||||
} elseif ($simple_html == 3) {
|
|
||||||
// The ! is converted to @ since Diaspora only understands the @
|
|
||||||
$text = preg_replace("/([@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
|
|
||||||
'@<a href="$2">$3</a>',
|
|
||||||
$text);
|
|
||||||
} elseif ($simple_html == 7) {
|
|
||||||
$text = preg_replace("/([@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
|
|
||||||
'$1<span class="vcard"><a href="$2" class="url u-url mention" title="$3"><span class="fn nickname mention">$3</span></a></span>',
|
|
||||||
$text);
|
|
||||||
} elseif (!$simple_html) {
|
|
||||||
$text = preg_replace("/([@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
|
|
||||||
'$1<a href="$2" class="userinfo mention" title="$3">$3</a>',
|
|
||||||
$text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bookmarks in red - will be converted to bookmarks in friendica
|
|
||||||
$text = preg_replace("/#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '[bookmark=$1]$1[/bookmark]', $text);
|
|
||||||
$text = preg_replace("/#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '[bookmark=$1]$2[/bookmark]', $text);
|
|
||||||
$text = preg_replace("/#\[url\=[$URLSearchString]*\]\^\[\/url\]\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/i",
|
|
||||||
"[bookmark=$1]$2[/bookmark]", $text);
|
|
||||||
|
|
||||||
if (in_array($simple_html, [2, 6, 7, 8, 9])) {
|
|
||||||
$text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", "self::expandLinksCallback", $text);
|
|
||||||
//$Text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $Text);
|
|
||||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]',$text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($simple_html == 5) {
|
|
||||||
$text = preg_replace("/[^#@!]\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '[url]$1[/url]', $text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform URL Search
|
|
||||||
if ($try_oembed) {
|
|
||||||
$text = preg_replace_callback("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", $try_oembed_callback, $text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($simple_html == 5) {
|
|
||||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url]$1[/url]', $text);
|
|
||||||
} else {
|
|
||||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url=$1]$2[/url]', $text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Diaspora posts
|
|
||||||
$text = preg_replace_callback(
|
|
||||||
"&\[url=/?posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
|
|
||||||
function ($match) {
|
|
||||||
return "[url=" . System::baseUrl() . "/display/" . $match[1] . "]" . $match[2] . "[/url]";
|
|
||||||
}, $text
|
|
||||||
);
|
|
||||||
|
|
||||||
$text = preg_replace_callback(
|
|
||||||
"&\[url=/people\?q\=(.*)\](.*)\[\/url\]&Usi",
|
|
||||||
function ($match) {
|
|
||||||
return "[url=" . System::baseUrl() . "/search?search=%40" . $match[1] . "]" . $match[2] . "[/url]";
|
|
||||||
}, $text
|
|
||||||
);
|
|
||||||
|
|
||||||
// Server independent link to posts and comments
|
|
||||||
// See issue: https://github.com/diaspora/diaspora_federation/issues/75
|
|
||||||
$expression = "=diaspora://.*?/post/([0-9A-Za-z\-_@.:]{15,254}[0-9A-Za-z])=ism";
|
|
||||||
$text = preg_replace($expression, System::baseUrl()."/display/$1", $text);
|
|
||||||
|
|
||||||
/* Tag conversion
|
|
||||||
* Supports:
|
|
||||||
* - #[url=<anything>]<term>[/url]
|
|
||||||
* - [url=<anything>]#<term>[/url]
|
|
||||||
*/
|
|
||||||
$text = preg_replace_callback("/(?:#\[url\=[$URLSearchString]*\]|\[url\=[$URLSearchString]*\]#)(.*?)\[\/url\]/ism", function($matches) {
|
|
||||||
return '#<a href="'
|
|
||||||
. System::baseUrl() . '/search?tag=' . rawurlencode($matches[1])
|
|
||||||
. '" class="tag" title="' . XML::escape($matches[1]) . '">'
|
|
||||||
. XML::escape($matches[1])
|
|
||||||
. '</a>';
|
|
||||||
}, $text);
|
|
||||||
|
|
||||||
// We need no target="_blank" for local links
|
|
||||||
// convert links start with System::baseUrl() as local link without the target="_blank" attribute
|
|
||||||
$escapedBaseUrl = preg_quote(System::baseUrl(), '/');
|
|
||||||
$text = preg_replace("/\[url\](".$escapedBaseUrl."[$URLSearchString]*)\[\/url\]/ism", '<a href="$1">$1</a>', $text);
|
|
||||||
$text = preg_replace("/\[url\=(".$escapedBaseUrl."[$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1">$2</a>', $text);
|
|
||||||
|
|
||||||
$text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$1</a>', $text);
|
|
||||||
$text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $text);
|
|
||||||
|
|
||||||
// Red compatibility, though the link can't be authenticated on Friendica
|
|
||||||
$text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a href="$1" target="_blank">$2</a>', $text);
|
|
||||||
|
|
||||||
|
|
||||||
// we may need to restrict this further if it picks up too many strays
|
|
||||||
// link acct:user@host to a webfinger profile redirector
|
|
||||||
|
|
||||||
$text = preg_replace('/acct:([^@]+)@((?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63})/', '<a href="' . System::baseUrl() . '/acctlink?addr=$1@$2" target="extlink">acct:$1@$2</a>', $text);
|
|
||||||
|
|
||||||
// Perform MAIL Search
|
|
||||||
$text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1">$1</a>', $text);
|
|
||||||
$text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1">$2</a>', $text);
|
|
||||||
|
|
||||||
// leave open the posibility of [map=something]
|
// leave open the posibility of [map=something]
|
||||||
// this is replaced in Item::prepareBody() which has knowledge of the item location
|
// this is replaced in Item::prepareBody() which has knowledge of the item location
|
||||||
|
|
||||||
if (strpos($text, '[/map]') !== false) {
|
if (strpos($text, '[/map]') !== false) {
|
||||||
$text = preg_replace_callback(
|
$text = preg_replace_callback(
|
||||||
"/\[map\](.*?)\[\/map\]/ism",
|
"/\[map\](.*?)\[\/map\]/ism",
|
||||||
|
@ -1396,6 +1291,7 @@ class BBCode extends BaseObject
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($text, '[map=') !== false) {
|
if (strpos($text, '[map=') !== false) {
|
||||||
$text = preg_replace_callback(
|
$text = preg_replace_callback(
|
||||||
"/\[map=(.*?)\]/ism",
|
"/\[map=(.*?)\]/ism",
|
||||||
|
@ -1405,6 +1301,7 @@ class BBCode extends BaseObject
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($text, '[map]') !== false) {
|
if (strpos($text, '[map]') !== false) {
|
||||||
$text = preg_replace("/\[map\]/", '<p class="map"></p>', $text);
|
$text = preg_replace("/\[map\]/", '<p class="map"></p>', $text);
|
||||||
}
|
}
|
||||||
|
@ -1471,9 +1368,9 @@ class BBCode extends BaseObject
|
||||||
$endlessloop = 0;
|
$endlessloop = 0;
|
||||||
|
|
||||||
while ((((strpos($text, "[/list]") !== false) && (strpos($text, "[list") !== false)) ||
|
while ((((strpos($text, "[/list]") !== false) && (strpos($text, "[list") !== false)) ||
|
||||||
((strpos($text, "[/ol]") !== false) && (strpos($text, "[ol]") !== false)) ||
|
((strpos($text, "[/ol]") !== false) && (strpos($text, "[ol]") !== false)) ||
|
||||||
((strpos($text, "[/ul]") !== false) && (strpos($text, "[ul]") !== false)) ||
|
((strpos($text, "[/ul]") !== false) && (strpos($text, "[ul]") !== false)) ||
|
||||||
((strpos($text, "[/li]") !== false) && (strpos($text, "[li]") !== false))) && (++$endlessloop < 20)) {
|
((strpos($text, "[/li]") !== false) && (strpos($text, "[li]") !== false))) && (++$endlessloop < 20)) {
|
||||||
$text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $text);
|
$text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $text);
|
||||||
$text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>', $text);
|
$text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>', $text);
|
||||||
$text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $text);
|
$text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $text);
|
||||||
|
@ -1521,8 +1418,8 @@ class BBCode extends BaseObject
|
||||||
$endlessloop = 0;
|
$endlessloop = 0;
|
||||||
while ((strpos($text, "[/spoiler]")!== false) && (strpos($text, "[spoiler=") !== false) && (++$endlessloop < 20)) {
|
while ((strpos($text, "[/spoiler]")!== false) && (strpos($text, "[spoiler=") !== false) && (++$endlessloop < 20)) {
|
||||||
$text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism",
|
$text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism",
|
||||||
"<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>",
|
"<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>",
|
||||||
$text);
|
$text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declare the format for [quote] layout
|
// Declare the format for [quote] layout
|
||||||
|
@ -1543,8 +1440,8 @@ class BBCode extends BaseObject
|
||||||
$endlessloop = 0;
|
$endlessloop = 0;
|
||||||
while ((strpos($text, "[/quote]")!== false) && (strpos($text, "[quote=") !== false) && (++$endlessloop < 20)) {
|
while ((strpos($text, "[/quote]")!== false) && (strpos($text, "[quote=") !== false) && (++$endlessloop < 20)) {
|
||||||
$text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism",
|
$text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism",
|
||||||
"<p><strong class=".'"author"'.">" . $t_wrote . "</strong></p><blockquote>$2</blockquote>",
|
"<p><strong class=".'"author"'.">" . $t_wrote . "</strong></p><blockquote>$2</blockquote>",
|
||||||
$text);
|
$text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1565,7 +1462,7 @@ class BBCode extends BaseObject
|
||||||
$text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $text);
|
$text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $text);
|
||||||
$text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" >', $text);
|
$text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" >', $text);
|
||||||
|
|
||||||
$text = preg_replace_callback("/\[img\=([$URLSearchString]*)\](.*?)\[\/img\]/ism",
|
$text = preg_replace_callback("/\[img\=(.*?)\](.*?)\[\/img\]/ism",
|
||||||
function ($matches) use ($simple_html) {
|
function ($matches) use ($simple_html) {
|
||||||
$matches[1] = self::proxyUrl($matches[1], $simple_html);
|
$matches[1] = self::proxyUrl($matches[1], $simple_html);
|
||||||
$matches[2] = htmlspecialchars($matches[2], ENT_COMPAT);
|
$matches[2] = htmlspecialchars($matches[2], ENT_COMPAT);
|
||||||
|
@ -1591,14 +1488,6 @@ class BBCode extends BaseObject
|
||||||
$text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . L10n::t('Image/photo') . '" />', $text);
|
$text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . L10n::t('Image/photo') . '" />', $text);
|
||||||
$text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img src="$1" alt="' . L10n::t('Image/photo') . '" />', $text);
|
$text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img src="$1" alt="' . L10n::t('Image/photo') . '" />', $text);
|
||||||
|
|
||||||
// Shared content
|
|
||||||
$text = self::convertShare(
|
|
||||||
$text,
|
|
||||||
function (array $attributes, array $author_contact, $content, $is_quote_share) use ($simple_html) {
|
|
||||||
return self::convertShareCallback($attributes, $author_contact, $content, $is_quote_share, $simple_html);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . L10n::t('Encrypted content') . '" /><br />', $text);
|
$text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . L10n::t('Encrypted content') . '" /><br />', $text);
|
||||||
$text = preg_replace("/\[crypt(.*?)\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . '$1' . ' ' . L10n::t('Encrypted content') . '" /><br />', $text);
|
$text = preg_replace("/\[crypt(.*?)\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . '$1' . ' ' . L10n::t('Encrypted content') . '" /><br />', $text);
|
||||||
//$Text = preg_replace("/\[crypt=(.*?)\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . '$1' . ' ' . L10n::t('Encrypted content') . '" /><br />', $Text);
|
//$Text = preg_replace("/\[crypt=(.*?)\](.*?)\[\/crypt\]/ism", '<br/><img src="' .System::baseUrl() . '/images/lock_icon.gif" alt="' . L10n::t('Encrypted content') . '" title="' . '$1' . ' ' . L10n::t('Encrypted content') . '" /><br />', $Text);
|
||||||
|
@ -1612,9 +1501,9 @@ class BBCode extends BaseObject
|
||||||
$text = preg_replace_callback("/\[audio\](.*?)\[\/audio\]/ism", $try_oembed_callback, $text);
|
$text = preg_replace_callback("/\[audio\](.*?)\[\/audio\]/ism", $try_oembed_callback, $text);
|
||||||
} else {
|
} else {
|
||||||
$text = preg_replace("/\[video\](.*?)\[\/video\]/ism",
|
$text = preg_replace("/\[video\](.*?)\[\/video\]/ism",
|
||||||
'<a href="$1" target="_blank">$1</a>', $text);
|
'<a href="$1" target="_blank">$1</a>', $text);
|
||||||
$text = preg_replace("/\[audio\](.*?)\[\/audio\]/ism",
|
$text = preg_replace("/\[audio\](.*?)\[\/audio\]/ism",
|
||||||
'<a href="$1" target="_blank">$1</a>', $text);
|
'<a href="$1" target="_blank">$1</a>', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// html5 video and audio
|
// html5 video and audio
|
||||||
|
@ -1641,7 +1530,7 @@ class BBCode extends BaseObject
|
||||||
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="https://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $text);
|
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="https://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $text);
|
||||||
} else {
|
} else {
|
||||||
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism",
|
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism",
|
||||||
'<a href="https://www.youtube.com/watch?v=$1" target="_blank">https://www.youtube.com/watch?v=$1</a>', $text);
|
'<a href="https://www.youtube.com/watch?v=$1" target="_blank">https://www.youtube.com/watch?v=$1</a>', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($try_oembed) {
|
if ($try_oembed) {
|
||||||
|
@ -1656,7 +1545,7 @@ class BBCode extends BaseObject
|
||||||
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="https://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $text);
|
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="https://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $text);
|
||||||
} else {
|
} else {
|
||||||
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism",
|
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism",
|
||||||
'<a href="https://vimeo.com/$1" target="_blank">https://vimeo.com/$1</a>', $text);
|
'<a href="https://vimeo.com/$1" target="_blank">https://vimeo.com/$1</a>', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// oembed tag
|
// oembed tag
|
||||||
|
@ -1687,6 +1576,120 @@ class BBCode extends BaseObject
|
||||||
$text = Smilies::replace($text);
|
$text = Smilies::replace($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the HTML is used to generate plain text, then don't do this search, but replace all URL of that kind to text
|
||||||
|
if (!$for_plaintext) {
|
||||||
|
$text = preg_replace(Strings::autoLinkRegEx(), '[url]$1[/url]', $text);
|
||||||
|
if (in_array($simple_html, [7, 9])) {
|
||||||
|
$text = preg_replace_callback("/\[url\](.*?)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
|
||||||
|
$text = preg_replace_callback("/\[url\=(.*?)\](.*?)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$text = preg_replace("(\[url\](.*?)\[\/url\])ism", " $1 ", $text);
|
||||||
|
$text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::removePictureLinksCallback', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = str_replace(["\r","\n"], ['<br />', '<br />'], $text);
|
||||||
|
|
||||||
|
// Remove all hashtag addresses
|
||||||
|
if ((!$try_oembed || $simple_html) && !in_array($simple_html, [3, 7, 9])) {
|
||||||
|
$text = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $text);
|
||||||
|
} elseif ($simple_html == 3) {
|
||||||
|
// The ! is converted to @ since Diaspora only understands the @
|
||||||
|
$text = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
|
||||||
|
'@<a href="$2">$3</a>',
|
||||||
|
$text);
|
||||||
|
} elseif (in_array($simple_html, [7, 9])) {
|
||||||
|
$text = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
|
||||||
|
'$1<span class="vcard"><a href="$2" class="url u-url mention" title="$3"><span class="fn nickname mention">$3</span></a></span>',
|
||||||
|
$text);
|
||||||
|
} elseif (!$simple_html) {
|
||||||
|
$text = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
|
||||||
|
'$1<a href="$2" class="userinfo mention" title="$3">$3</a>',
|
||||||
|
$text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bookmarks in red - will be converted to bookmarks in friendica
|
||||||
|
$text = preg_replace("/#\^\[url\](.*?)\[\/url\]/ism", '[bookmark=$1]$1[/bookmark]', $text);
|
||||||
|
$text = preg_replace("/#\^\[url\=(.*?)\](.*?)\[\/url\]/ism", '[bookmark=$1]$2[/bookmark]', $text);
|
||||||
|
$text = preg_replace("/#\[url\=.*?\]\^\[\/url\]\[url\=(.*?)\](.*?)\[\/url\]/i",
|
||||||
|
"[bookmark=$1]$2[/bookmark]", $text);
|
||||||
|
|
||||||
|
if (in_array($simple_html, [2, 6, 7, 8])) {
|
||||||
|
$text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", "self::expandLinksCallback", $text);
|
||||||
|
//$Text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $Text);
|
||||||
|
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]',$text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($simple_html == 5) {
|
||||||
|
$text = preg_replace("/[^#@!]\[url\=(.*?)\](.*?)\[\/url\]/ism", '[url]$1[/url]', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform URL Search
|
||||||
|
if ($try_oembed) {
|
||||||
|
$text = preg_replace_callback("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", $try_oembed_callback, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($simple_html == 5) {
|
||||||
|
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url]$1[/url]', $text);
|
||||||
|
} else {
|
||||||
|
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url=$1]$2[/url]', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Diaspora posts
|
||||||
|
$text = preg_replace_callback(
|
||||||
|
"&\[url=/?posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
|
||||||
|
function ($match) {
|
||||||
|
return "[url=" . System::baseUrl() . "/display/" . $match[1] . "]" . $match[2] . "[/url]";
|
||||||
|
}, $text
|
||||||
|
);
|
||||||
|
|
||||||
|
$text = preg_replace_callback(
|
||||||
|
"&\[url=/people\?q\=(.*)\](.*)\[\/url\]&Usi",
|
||||||
|
function ($match) {
|
||||||
|
return "[url=" . System::baseUrl() . "/search?search=%40" . $match[1] . "]" . $match[2] . "[/url]";
|
||||||
|
}, $text
|
||||||
|
);
|
||||||
|
|
||||||
|
// Server independent link to posts and comments
|
||||||
|
// See issue: https://github.com/diaspora/diaspora_federation/issues/75
|
||||||
|
$expression = "=diaspora://.*?/post/([0-9A-Za-z\-_@.:]{15,254}[0-9A-Za-z])=ism";
|
||||||
|
$text = preg_replace($expression, System::baseUrl()."/display/$1", $text);
|
||||||
|
|
||||||
|
/* Tag conversion
|
||||||
|
* Supports:
|
||||||
|
* - #[url=<anything>]<term>[/url]
|
||||||
|
* - [url=<anything>]#<term>[/url]
|
||||||
|
*/
|
||||||
|
$text = preg_replace_callback("/(?:#\[url\=.*?\]|\[url\=.*?\]#)(.*?)\[\/url\]/ism", function($matches) {
|
||||||
|
return '#<a href="'
|
||||||
|
. System::baseUrl() . '/search?tag=' . rawurlencode($matches[1])
|
||||||
|
. '" class="tag" title="' . XML::escape($matches[1]) . '">'
|
||||||
|
. XML::escape($matches[1])
|
||||||
|
. '</a>';
|
||||||
|
}, $text);
|
||||||
|
|
||||||
|
// We need no target="_blank" for local links
|
||||||
|
// convert links start with System::baseUrl() as local link without the target="_blank" attribute
|
||||||
|
$escapedBaseUrl = preg_quote(System::baseUrl(), '/');
|
||||||
|
$text = preg_replace("/\[url\](".$escapedBaseUrl.".*?)\[\/url\]/ism", '<a href="$1">$1</a>', $text);
|
||||||
|
$text = preg_replace("/\[url\=(".$escapedBaseUrl.".*?)\](.*?)\[\/url\]/ism", '<a href="$1">$2</a>', $text);
|
||||||
|
|
||||||
|
$text = preg_replace("/\[url\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$1</a>', $text);
|
||||||
|
$text = preg_replace("/\[url\=(.*?)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $text);
|
||||||
|
|
||||||
|
// Red compatibility, though the link can't be authenticated on Friendica
|
||||||
|
$text = preg_replace("/\[zrl\=(.*?)\](.*?)\[\/zrl\]/ism", '<a href="$1" target="_blank">$2</a>', $text);
|
||||||
|
|
||||||
|
|
||||||
|
// we may need to restrict this further if it picks up too many strays
|
||||||
|
// link acct:user@host to a webfinger profile redirector
|
||||||
|
|
||||||
|
$text = preg_replace('/acct:([^@]+)@((?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63})/', '<a href="' . System::baseUrl() . '/acctlink?addr=$1@$2" target="extlink">acct:$1@$2</a>', $text);
|
||||||
|
|
||||||
|
// Perform MAIL Search
|
||||||
|
$text = preg_replace("/\[mail\](.*?)\[\/mail\]/", '<a href="mailto:$1">$1</a>', $text);
|
||||||
|
$text = preg_replace("/\[mail\=(.*?)\](.*?)\[\/mail\]/", '<a href="mailto:$1">$2</a>', $text);
|
||||||
|
|
||||||
// Unhide all [noparse] contained bbtags unspacefying them
|
// Unhide all [noparse] contained bbtags unspacefying them
|
||||||
// and triming the [noparse] tag.
|
// and triming the [noparse] tag.
|
||||||
|
|
||||||
|
@ -1720,6 +1723,14 @@ class BBCode extends BaseObject
|
||||||
$regex = '#<([^>]*?)(href)="(?!' . implode('|', $allowed_link_protocols) . ')(.*?)"(.*?)>#ism';
|
$regex = '#<([^>]*?)(href)="(?!' . implode('|', $allowed_link_protocols) . ')(.*?)"(.*?)>#ism';
|
||||||
$text = preg_replace($regex, '<$1$2="javascript:void(0)"$4 data-original-href="$3" class="invalid-href" title="' . L10n::t('Invalid link protocol') . '">', $text);
|
$text = preg_replace($regex, '<$1$2="javascript:void(0)"$4 data-original-href="$3" class="invalid-href" title="' . L10n::t('Invalid link protocol') . '">', $text);
|
||||||
|
|
||||||
|
// Shared content
|
||||||
|
$text = self::convertShare(
|
||||||
|
$text,
|
||||||
|
function (array $attributes, array $author_contact, $content, $is_quote_share) use ($simple_html) {
|
||||||
|
return self::convertShareCallback($attributes, $author_contact, $content, $is_quote_share, $simple_html);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if ($saved_image) {
|
if ($saved_image) {
|
||||||
$text = self::interpolateSavedImagesIntoItemBody($text, $saved_image);
|
$text = self::interpolateSavedImagesIntoItemBody($text, $saved_image);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,12 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\FileTag;
|
use Friendica\Model\FileTag;
|
||||||
use Friendica\Model\GContact;
|
use Friendica\Model\GContact;
|
||||||
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Proxy as ProxyUtils;
|
use Friendica\Util\Proxy as ProxyUtils;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Util\Temporal;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
|
||||||
class Widget
|
class Widget
|
||||||
|
@ -121,17 +124,28 @@ class Widget
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* Display a generic filter widget based on a list of options
|
||||||
|
*
|
||||||
|
* The options array must be the following format:
|
||||||
|
* [
|
||||||
|
* [
|
||||||
|
* 'ref' => {filter value},
|
||||||
|
* 'name' => {option name}
|
||||||
|
* ],
|
||||||
|
* ...
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* @param string $type The filter query string key
|
||||||
* @param string $title
|
* @param string $title
|
||||||
* @param string $desc
|
* @param string $desc
|
||||||
* @param string $all
|
* @param string $all The no filter label
|
||||||
* @param string $baseUrl
|
* @param string $baseUrl The full page request URI
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @param string $selected
|
* @param string $selected The currently selected filter option value
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function filter($type, $title, $desc, $all, $baseUrl, array $options, $selected = null)
|
private static function filter($type, $title, $desc, $all, $baseUrl, array $options, $selected = null)
|
||||||
{
|
{
|
||||||
$queryString = parse_url($baseUrl, PHP_URL_QUERY);
|
$queryString = parse_url($baseUrl, PHP_URL_QUERY);
|
||||||
$queryArray = [];
|
$queryArray = [];
|
||||||
|
@ -160,6 +174,37 @@ class Widget
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return networks widget
|
||||||
|
*
|
||||||
|
* @param string $baseurl baseurl
|
||||||
|
* @param string $selected optional, default empty
|
||||||
|
* @return string
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function contactRels($baseurl, $selected = '')
|
||||||
|
{
|
||||||
|
if (!local_user()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
['ref' => 'followers', 'name' => L10n::t('Followers')],
|
||||||
|
['ref' => 'following', 'name' => L10n::t('Following')],
|
||||||
|
['ref' => 'mutuals', 'name' => L10n::t('Mutual friends')],
|
||||||
|
];
|
||||||
|
|
||||||
|
return self::filter(
|
||||||
|
'rel',
|
||||||
|
L10n::t('Relationships'),
|
||||||
|
'',
|
||||||
|
L10n::t('All Contacts'),
|
||||||
|
$baseurl,
|
||||||
|
$options,
|
||||||
|
$selected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return networks widget
|
* Return networks widget
|
||||||
*
|
*
|
||||||
|
@ -211,7 +256,7 @@ class Widget
|
||||||
* @param string $baseurl baseurl
|
* @param string $baseurl baseurl
|
||||||
* @param string $selected optional, default empty
|
* @param string $selected optional, default empty
|
||||||
* @return string|void
|
* @return string|void
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function fileAs($baseurl, $selected = '')
|
public static function fileAs($baseurl, $selected = '')
|
||||||
{
|
{
|
||||||
|
@ -224,15 +269,9 @@ class Widget
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$matches = [];
|
$terms = [];
|
||||||
$terms = array();
|
foreach (FileTag::fileToArray($saved) as $savedFolderName) {
|
||||||
$cnt = preg_match_all('/\[(.*?)\]/', $saved, $matches, PREG_SET_ORDER);
|
$terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName];
|
||||||
if ($cnt) {
|
|
||||||
foreach ($matches as $mtch)
|
|
||||||
{
|
|
||||||
$unescaped = XML::escape(FileTag::decode($mtch[1]));
|
|
||||||
$terms[] = ['ref' => $unescaped, 'name' => $unescaped];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::filter(
|
return self::filter(
|
||||||
|
@ -267,15 +306,9 @@ class Widget
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$matches = [];
|
|
||||||
$terms = array();
|
$terms = array();
|
||||||
$cnt = preg_match_all('/<(.*?)>/', $saved, $matches, PREG_SET_ORDER);
|
foreach (FileTag::fileToArray($saved, 'category') as $savedFolderName) {
|
||||||
|
$terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName];
|
||||||
if ($cnt) {
|
|
||||||
foreach ($matches as $mtch) {
|
|
||||||
$unescaped = XML::escape(FileTag::decode($mtch[1]));
|
|
||||||
$terms[] = ['ref' => $unescaped, 'name' => $unescaped];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::filter(
|
return self::filter(
|
||||||
|
@ -402,4 +435,74 @@ class Widget
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $url Base page URL
|
||||||
|
* @param int $uid User ID consulting/publishing posts
|
||||||
|
* @param bool $wall True: Posted by User; False: Posted to User (network timeline)
|
||||||
|
* @return string
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public static function postedByYear(string $url, int $uid, bool $wall)
|
||||||
|
{
|
||||||
|
$o = '';
|
||||||
|
|
||||||
|
if (!Feature::isEnabled($uid, 'archives')) {
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
$visible_years = PConfig::get($uid, 'system', 'archive_visible_years', 5);
|
||||||
|
|
||||||
|
/* arrange the list in years */
|
||||||
|
$dnow = DateTimeFormat::localNow('Y-m-d');
|
||||||
|
|
||||||
|
$ret = [];
|
||||||
|
|
||||||
|
$dthen = Item::firstPostDate($uid, $wall);
|
||||||
|
if ($dthen) {
|
||||||
|
// Set the start and end date to the beginning of the month
|
||||||
|
$dnow = substr($dnow, 0, 8) . '01';
|
||||||
|
$dthen = substr($dthen, 0, 8) . '01';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starting with the current month, get the first and last days of every
|
||||||
|
* month down to and including the month of the first post
|
||||||
|
*/
|
||||||
|
while (substr($dnow, 0, 7) >= substr($dthen, 0, 7)) {
|
||||||
|
$dyear = intval(substr($dnow, 0, 4));
|
||||||
|
$dstart = substr($dnow, 0, 8) . '01';
|
||||||
|
$dend = substr($dnow, 0, 8) . Temporal::getDaysInMonth(intval($dnow), intval(substr($dnow, 5)));
|
||||||
|
$start_month = DateTimeFormat::utc($dstart, 'Y-m-d');
|
||||||
|
$end_month = DateTimeFormat::utc($dend, 'Y-m-d');
|
||||||
|
$str = L10n::getDay(DateTimeFormat::utc($dnow, 'F'));
|
||||||
|
|
||||||
|
if (empty($ret[$dyear])) {
|
||||||
|
$ret[$dyear] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret[$dyear][] = [$str, $end_month, $start_month];
|
||||||
|
$dnow = DateTimeFormat::utc($dnow . ' -1 month', 'Y-m-d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DBA::isResult($ret)) {
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$cutoff_year = intval(DateTimeFormat::localNow('Y')) - $visible_years;
|
||||||
|
$cutoff = array_key_exists($cutoff_year, $ret);
|
||||||
|
|
||||||
|
$o = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/posted_date.tpl'),[
|
||||||
|
'$title' => L10n::t('Archives'),
|
||||||
|
'$size' => $visible_years,
|
||||||
|
'$cutoff_year' => $cutoff_year,
|
||||||
|
'$cutoff' => $cutoff,
|
||||||
|
'$url' => $url,
|
||||||
|
'$dates' => $ret,
|
||||||
|
'$showmore' => L10n::t('show more')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ContactBlock
|
||||||
'pending' => false,
|
'pending' => false,
|
||||||
'hidden' => false,
|
'hidden' => false,
|
||||||
'archive' => false,
|
'archive' => false,
|
||||||
'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA],
|
'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::FEED],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$contacts_title = L10n::t('No contacts');
|
$contacts_title = L10n::t('No contacts');
|
||||||
|
|
|
@ -259,7 +259,7 @@ class ACL extends BaseObject
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function getFullSelectorHTML(array $user, $show_jotnets = false, array $default_permissions = [])
|
public static function getFullSelectorHTML(array $user = null, $show_jotnets = false, array $default_permissions = [])
|
||||||
{
|
{
|
||||||
// Defaults user permissions
|
// Defaults user permissions
|
||||||
if (empty($default_permissions)) {
|
if (empty($default_permissions)) {
|
||||||
|
@ -314,7 +314,7 @@ class ACL extends BaseObject
|
||||||
'$aclModalTitle' => L10n::t('Permissions'),
|
'$aclModalTitle' => L10n::t('Permissions'),
|
||||||
'$aclModalDismiss' => L10n::t('Close'),
|
'$aclModalDismiss' => L10n::t('Close'),
|
||||||
'$features' => [
|
'$features' => [
|
||||||
'aclautomention' => Feature::isEnabled($user['uid'], 'aclautomention') ? 'true' : 'false'
|
'aclautomention' => !empty($user['uid']) && Feature::isEnabled($user['uid'], 'aclautomention') ? 'true' : 'false'
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Friendica\Core\Config\Cache;
|
namespace Friendica\Core\Config\Cache;
|
||||||
|
|
||||||
|
use ParagonIE\HiddenString\HiddenString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Friendica config cache for the application
|
* The Friendica config cache for the application
|
||||||
* Initial, all *.config.php files are loaded into this cache with the
|
* Initial, all *.config.php files are loaded into this cache with the
|
||||||
|
@ -15,10 +17,17 @@ class ConfigCache implements IConfigCache, IPConfigCache
|
||||||
private $config;
|
private $config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $config A initial config array
|
* @var bool
|
||||||
*/
|
*/
|
||||||
public function __construct(array $config = [])
|
private $hidePasswordOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $config A initial config array
|
||||||
|
* @param bool $hidePasswordOutput True, if cache variables should take extra care of password values
|
||||||
|
*/
|
||||||
|
public function __construct(array $config = [], $hidePasswordOutput = true)
|
||||||
{
|
{
|
||||||
|
$this->hidePasswordOutput = $hidePasswordOutput;
|
||||||
$this->load($config);
|
$this->load($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +93,13 @@ class ConfigCache implements IConfigCache, IPConfigCache
|
||||||
$this->config[$cat] = [];
|
$this->config[$cat] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->config[$cat][$key] = $value;
|
if ($this->hidePasswordOutput &&
|
||||||
|
$key == 'password' &&
|
||||||
|
!empty($value) && is_string($value)) {
|
||||||
|
$this->config[$cat][$key] = new HiddenString((string) $value);
|
||||||
|
} else {
|
||||||
|
$this->config[$cat][$key] = $value;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ class Configuration
|
||||||
|
|
||||||
if (isset($dbvalue)) {
|
if (isset($dbvalue)) {
|
||||||
$this->configCache->set($cat, $key, $dbvalue);
|
$this->configCache->set($cat, $key, $dbvalue);
|
||||||
return $dbvalue;
|
unset($dbvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ class Installer
|
||||||
'$basepath' => $basepath,
|
'$basepath' => $basepath,
|
||||||
'$timezone' => $configCache->get('system', 'default_timezone'),
|
'$timezone' => $configCache->get('system', 'default_timezone'),
|
||||||
'$language' => $configCache->get('system', 'language'),
|
'$language' => $configCache->get('system', 'language'),
|
||||||
], false);
|
]);
|
||||||
|
|
||||||
$result = file_put_contents($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php', $txt);
|
$result = file_put_contents($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php', $txt);
|
||||||
|
|
||||||
|
|
244
src/Core/Search.php
Normal file
244
src/Core/Search.php
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Core;
|
||||||
|
|
||||||
|
use Friendica\BaseObject;
|
||||||
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Model\Contact;
|
||||||
|
use Friendica\Network\HTTPException;
|
||||||
|
use Friendica\Network\Probe;
|
||||||
|
use Friendica\Object\Search\ContactResult;
|
||||||
|
use Friendica\Object\Search\ResultList;
|
||||||
|
use Friendica\Protocol\PortableContact;
|
||||||
|
use Friendica\Util\Network;
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific class to perform searches for different systems. Currently:
|
||||||
|
* - Probe for contacts
|
||||||
|
* - Search in the local directory
|
||||||
|
* - Search in the global directory
|
||||||
|
*/
|
||||||
|
class Search extends BaseObject
|
||||||
|
{
|
||||||
|
const DEFAULT_DIRECTORY = 'https://dir.friendica.social';
|
||||||
|
|
||||||
|
const TYPE_PEOPLE = 0;
|
||||||
|
const TYPE_FORUM = 1;
|
||||||
|
const TYPE_ALL = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search a user based on his/her profile address
|
||||||
|
* pattern: @username@domain.tld
|
||||||
|
*
|
||||||
|
* @param string $user The user to search for
|
||||||
|
*
|
||||||
|
* @return ResultList
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
public static function getContactsFromProbe($user)
|
||||||
|
{
|
||||||
|
$emptyResultList = new ResultList(1, 0, 1);
|
||||||
|
|
||||||
|
if ((filter_var($user, FILTER_VALIDATE_EMAIL) && Network::isEmailDomainValid($user)) ||
|
||||||
|
(substr(Strings::normaliseLink($user), 0, 7) == "http://")) {
|
||||||
|
|
||||||
|
$user_data = Probe::uri($user);
|
||||||
|
if (empty($user_data)) {
|
||||||
|
return $emptyResultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]))) {
|
||||||
|
return $emptyResultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contactDetails = Contact::getDetailsByURL(defaults($user_data, 'url', ''), local_user());
|
||||||
|
$itemUrl = defaults($contactDetails, 'addr', defaults($user_data, 'url', ''));
|
||||||
|
|
||||||
|
$result = new ContactResult(
|
||||||
|
defaults($user_data, 'name', ''),
|
||||||
|
defaults($user_data, 'addr', ''),
|
||||||
|
$itemUrl,
|
||||||
|
defaults($user_data, 'url', ''),
|
||||||
|
defaults($user_data, 'photo', ''),
|
||||||
|
defaults($user_data, 'network', ''),
|
||||||
|
defaults($contactDetails, 'cid', 0),
|
||||||
|
0,
|
||||||
|
defaults($user_data, 'tags', '')
|
||||||
|
);
|
||||||
|
|
||||||
|
return new ResultList(1, 1, 1, [$result]);
|
||||||
|
} else {
|
||||||
|
return $emptyResultList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search in the global directory for occurrences of the search string
|
||||||
|
*
|
||||||
|
* @see https://github.com/friendica/friendica-directory/blob/master/docs/Protocol.md#search
|
||||||
|
*
|
||||||
|
* @param string $search
|
||||||
|
* @param int $type specific type of searching
|
||||||
|
* @param int $page
|
||||||
|
*
|
||||||
|
* @return ResultList
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public static function getContactsFromGlobalDirectory($search, $type = self::TYPE_ALL, $page = 1)
|
||||||
|
{
|
||||||
|
$config = self::getApp()->getConfig();
|
||||||
|
$server = $config->get('system', 'directory', self::DEFAULT_DIRECTORY);
|
||||||
|
|
||||||
|
$searchUrl = $server . '/search';
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case self::TYPE_FORUM:
|
||||||
|
$searchUrl .= '/forum';
|
||||||
|
break;
|
||||||
|
case self::TYPE_PEOPLE:
|
||||||
|
$searchUrl .= '/people';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$searchUrl .= '?q=' . urlencode($search);
|
||||||
|
|
||||||
|
if ($page > 1) {
|
||||||
|
$searchUrl .= '&page=' . $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
$resultJson = Network::fetchUrl($searchUrl, false, 0, 'application/json');
|
||||||
|
|
||||||
|
$results = json_decode($resultJson, true);
|
||||||
|
|
||||||
|
$resultList = new ResultList(
|
||||||
|
defaults($results, 'page', 1),
|
||||||
|
defaults($results, 'count', 0),
|
||||||
|
defaults($results, 'itemsperpage', 30)
|
||||||
|
);
|
||||||
|
|
||||||
|
$profiles = defaults($results, 'profiles', []);
|
||||||
|
|
||||||
|
foreach ($profiles as $profile) {
|
||||||
|
$contactDetails = Contact::getDetailsByURL(defaults($profile, 'profile_url', ''), local_user());
|
||||||
|
$itemUrl = defaults($contactDetails, 'addr', defaults($profile, 'profile_url', ''));
|
||||||
|
|
||||||
|
$result = new ContactResult(
|
||||||
|
defaults($profile, 'name', ''),
|
||||||
|
defaults($profile, 'addr', ''),
|
||||||
|
$itemUrl,
|
||||||
|
defaults($profile, 'profile_url', ''),
|
||||||
|
defaults($profile, 'photo', ''),
|
||||||
|
Protocol::DFRN,
|
||||||
|
defaults($contactDetails, 'cid', 0),
|
||||||
|
0,
|
||||||
|
defaults($profile, 'tags', ''));
|
||||||
|
|
||||||
|
$resultList->addResult($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search in the local database for occurrences of the search string
|
||||||
|
*
|
||||||
|
* @param string $search
|
||||||
|
* @param int $type
|
||||||
|
* @param int $start
|
||||||
|
* @param int $itemPage
|
||||||
|
*
|
||||||
|
* @return ResultList
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public static function getContactsFromLocalDirectory($search, $type = self::TYPE_ALL, $start = 0, $itemPage = 80)
|
||||||
|
{
|
||||||
|
$config = self::getApp()->getConfig();
|
||||||
|
|
||||||
|
$diaspora = $config->get('system', 'diaspora_enabled') ? Protocol::DIASPORA : Protocol::DFRN;
|
||||||
|
$ostatus = !$config->get('system', 'ostatus_disabled') ? Protocol::OSTATUS : Protocol::DFRN;
|
||||||
|
|
||||||
|
$wildcard = Strings::escapeHtml('%' . $search . '%');
|
||||||
|
|
||||||
|
$count = DBA::count('gcontact', [
|
||||||
|
'NOT `hide`
|
||||||
|
AND `network` IN (?, ?, ?, ?)
|
||||||
|
AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`))
|
||||||
|
AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ?
|
||||||
|
OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?)
|
||||||
|
AND `community` = ?',
|
||||||
|
Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora,
|
||||||
|
$wildcard, $wildcard, $wildcard,
|
||||||
|
$wildcard, $wildcard, $wildcard,
|
||||||
|
($type === self::TYPE_FORUM),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$resultList = new ResultList($start, $itemPage, $count);
|
||||||
|
|
||||||
|
if (empty($count)) {
|
||||||
|
return $resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = DBA::select('gcontact', ['nurl'], [
|
||||||
|
'NOT `hide`
|
||||||
|
AND `network` IN (?, ?, ?, ?)
|
||||||
|
AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`))
|
||||||
|
AND (`url` LIKE ? OR `name` LIKE ? OR `location` LIKE ?
|
||||||
|
OR `addr` LIKE ? OR `about` LIKE ? OR `keywords` LIKE ?)
|
||||||
|
AND `community` = ?',
|
||||||
|
Protocol::ACTIVITYPUB, Protocol::DFRN, $ostatus, $diaspora,
|
||||||
|
$wildcard, $wildcard, $wildcard,
|
||||||
|
$wildcard, $wildcard, $wildcard,
|
||||||
|
($type === self::TYPE_FORUM),
|
||||||
|
], [
|
||||||
|
'group_by' => ['nurl', 'updated'],
|
||||||
|
'limit' => [$start, $itemPage],
|
||||||
|
'order' => ['updated' => 'DESC']
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!DBA::isResult($data)) {
|
||||||
|
return $resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($row = DBA::fetch($data)) {
|
||||||
|
if (PortableContact::alternateOStatusUrl($row["nurl"])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$urlParts = parse_url($row["nurl"]);
|
||||||
|
|
||||||
|
// Ignore results that look strange.
|
||||||
|
// For historic reasons the gcontact table does contain some garbage.
|
||||||
|
if (!empty($urlParts['query']) || !empty($urlParts['fragment'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact = Contact::getDetailsByURL($row["nurl"], local_user());
|
||||||
|
|
||||||
|
if ($contact["name"] == "") {
|
||||||
|
$contact["name"] = end(explode("/", $urlParts["path"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = new ContactResult(
|
||||||
|
$contact["name"],
|
||||||
|
$contact["addr"],
|
||||||
|
$contact["addr"],
|
||||||
|
$contact["url"],
|
||||||
|
$contact["photo"],
|
||||||
|
$contact["network"],
|
||||||
|
$contact["cid"],
|
||||||
|
$contact["zid"],
|
||||||
|
$contact["keywords"]
|
||||||
|
);
|
||||||
|
|
||||||
|
$resultList->addResult($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBA::close($data);
|
||||||
|
|
||||||
|
// Add found profiles from the global directory to the local directory
|
||||||
|
Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search));
|
||||||
|
|
||||||
|
return $resultList;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use Friendica\Database\DBStructure;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UserImport class
|
* @brief UserImport class
|
||||||
|
@ -39,14 +40,21 @@ class UserImport
|
||||||
$tableColumns = DBStructure::getColumns($table);
|
$tableColumns = DBStructure::getColumns($table);
|
||||||
|
|
||||||
$tcols = [];
|
$tcols = [];
|
||||||
|
$ttype = [];
|
||||||
// get a plain array of column names
|
// get a plain array of column names
|
||||||
foreach ($tableColumns as $tcol) {
|
foreach ($tableColumns as $tcol) {
|
||||||
$tcols[] = $tcol['Field'];
|
$tcols[] = $tcol['Field'];
|
||||||
|
$ttype[$tcol['Field']] = $tcol['Type'];
|
||||||
}
|
}
|
||||||
// remove inexistent columns
|
// remove inexistent columns
|
||||||
foreach ($arr as $icol => $ival) {
|
foreach ($arr as $icol => $ival) {
|
||||||
if (!in_array($icol, $tcols)) {
|
if (!in_array($icol, $tcols)) {
|
||||||
unset($arr[$icol]);
|
unset($arr[$icol]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ttype[$icol] === 'datetime') {
|
||||||
|
$arr[$icol] = $ival ?? DBA::NULL_DATETIME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +279,7 @@ class UserImport
|
||||||
}
|
}
|
||||||
|
|
||||||
// send relocate messages
|
// send relocate messages
|
||||||
Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $newuid);
|
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $newuid);
|
||||||
|
|
||||||
info(L10n::t("Done. You can now login with your username and password"));
|
info(L10n::t("Done. You can now login with your username and password"));
|
||||||
$a->internalRedirect('login');
|
$a->internalRedirect('login');
|
||||||
|
|
|
@ -983,7 +983,7 @@ class Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = System::baseUrl()."/worker";
|
$url = System::baseUrl()."/worker";
|
||||||
Network::fetchUrl($url, false, $redirects, 1);
|
Network::fetchUrl($url, false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1100,7 +1100,7 @@ class Worker
|
||||||
* @param (integer|array) priority or parameter array, strings are deprecated and are ignored
|
* @param (integer|array) priority or parameter array, strings are deprecated and are ignored
|
||||||
*
|
*
|
||||||
* next args are passed as $cmd command line
|
* next args are passed as $cmd command line
|
||||||
* or: Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
|
* or: Worker::add(PRIORITY_HIGH, "Notifier", Delivery::DELETION, $drop_id);
|
||||||
* or: Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowEntry", $post_id);
|
* or: Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowEntry", $post_id);
|
||||||
*
|
*
|
||||||
* @return boolean "false" if proc_run couldn't be executed
|
* @return boolean "false" if proc_run couldn't be executed
|
||||||
|
|
|
@ -45,6 +45,7 @@ class DBA
|
||||||
*/
|
*/
|
||||||
private static $logger;
|
private static $logger;
|
||||||
private static $server_info = '';
|
private static $server_info = '';
|
||||||
|
/** @var PDO|mysqli */
|
||||||
private static $connection;
|
private static $connection;
|
||||||
private static $driver;
|
private static $driver;
|
||||||
private static $error = false;
|
private static $error = false;
|
||||||
|
@ -288,6 +289,19 @@ class DBA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes every not whitelisted character from the identifier string
|
||||||
|
*
|
||||||
|
* @param string $identifier
|
||||||
|
*
|
||||||
|
* @return string sanitized identifier
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private static function sanitizeIdentifier($identifier)
|
||||||
|
{
|
||||||
|
return preg_replace('/[^A-Za-z0-9_\-]+/', '', $identifier);
|
||||||
|
}
|
||||||
|
|
||||||
public static function escape($str) {
|
public static function escape($str) {
|
||||||
if (self::$connected) {
|
if (self::$connected) {
|
||||||
switch (self::$driver) {
|
switch (self::$driver) {
|
||||||
|
@ -483,6 +497,7 @@ class DBA
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var $stmt mysqli_stmt|PDOStatement */
|
||||||
if (!$stmt = self::$connection->prepare($sql)) {
|
if (!$stmt = self::$connection->prepare($sql)) {
|
||||||
$errorInfo = self::$connection->errorInfo();
|
$errorInfo = self::$connection->errorInfo();
|
||||||
self::$error = $errorInfo[2];
|
self::$error = $errorInfo[2];
|
||||||
|
@ -872,6 +887,29 @@ class DBA
|
||||||
return $columns;
|
return $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Insert a row into a table
|
||||||
|
*
|
||||||
|
* @param string/array $table Table name
|
||||||
|
*
|
||||||
|
* @return string formatted and sanitzed table name
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function formatTableName($table)
|
||||||
|
{
|
||||||
|
if (is_string($table)) {
|
||||||
|
return "`" . self::sanitizeIdentifier($table) . "`";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($table)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$scheme = key($table);
|
||||||
|
|
||||||
|
return "`" . self::sanitizeIdentifier($scheme) . "`.`" . self::sanitizeIdentifier($table[$scheme]) . "`";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Insert a row into a table
|
* @brief Insert a row into a table
|
||||||
*
|
*
|
||||||
|
@ -889,7 +927,7 @@ class DBA
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = "INSERT INTO `".self::escape($table)."` (`".implode("`, `", array_keys($param))."`) VALUES (".
|
$sql = "INSERT INTO " . self::formatTableName($table) . " (`".implode("`, `", array_keys($param))."`) VALUES (".
|
||||||
substr(str_repeat("?, ", count($param)), 0, -2).")";
|
substr(str_repeat("?, ", count($param)), 0, -2).")";
|
||||||
|
|
||||||
if ($on_duplicate_update) {
|
if ($on_duplicate_update) {
|
||||||
|
@ -938,7 +976,7 @@ class DBA
|
||||||
self::$connection->autocommit(false);
|
self::$connection->autocommit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$success = self::e("LOCK TABLES `".self::escape($table)."` WRITE");
|
$success = self::e("LOCK TABLES " . self::formatTableName($table) ." WRITE");
|
||||||
|
|
||||||
if (self::$driver == 'pdo') {
|
if (self::$driver == 'pdo') {
|
||||||
self::$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
self::$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||||
|
@ -1119,7 +1157,7 @@ class DBA
|
||||||
|
|
||||||
$callstack[$key] = true;
|
$callstack[$key] = true;
|
||||||
|
|
||||||
$table = self::escape($table);
|
$table = self::sanitizeIdentifier($table);
|
||||||
|
|
||||||
$commands[$key] = ['table' => $table, 'conditions' => $conditions];
|
$commands[$key] = ['table' => $table, 'conditions' => $conditions];
|
||||||
|
|
||||||
|
@ -1272,8 +1310,6 @@ class DBA
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = self::escape($table);
|
|
||||||
|
|
||||||
$condition_string = self::buildCondition($condition);
|
$condition_string = self::buildCondition($condition);
|
||||||
|
|
||||||
if (is_bool($old_fields)) {
|
if (is_bool($old_fields)) {
|
||||||
|
@ -1306,7 +1342,7 @@ class DBA
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = "UPDATE `".$table."` SET `".
|
$sql = "UPDATE ". self::formatTableName($table) . " SET `".
|
||||||
implode("` = ?, `", array_keys($fields))."` = ?".$condition_string;
|
implode("` = ?, `", array_keys($fields))."` = ?".$condition_string;
|
||||||
|
|
||||||
$params1 = array_values($fields);
|
$params1 = array_values($fields);
|
||||||
|
@ -1367,12 +1403,10 @@ class DBA
|
||||||
*/
|
*/
|
||||||
public static function select($table, array $fields = [], array $condition = [], array $params = [])
|
public static function select($table, array $fields = [], array $condition = [], array $params = [])
|
||||||
{
|
{
|
||||||
if ($table == '') {
|
if (empty($table)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = self::escape($table);
|
|
||||||
|
|
||||||
if (count($fields) > 0) {
|
if (count($fields) > 0) {
|
||||||
$select_fields = "`" . implode("`, `", array_values($fields)) . "`";
|
$select_fields = "`" . implode("`, `", array_values($fields)) . "`";
|
||||||
} else {
|
} else {
|
||||||
|
@ -1383,7 +1417,7 @@ class DBA
|
||||||
|
|
||||||
$param_string = self::buildParameter($params);
|
$param_string = self::buildParameter($params);
|
||||||
|
|
||||||
$sql = "SELECT " . $select_fields . " FROM `" . $table . "`" . $condition_string . $param_string;
|
$sql = "SELECT " . $select_fields . " FROM " . self::formatTableName($table) . $condition_string . $param_string;
|
||||||
|
|
||||||
$result = self::p($sql, $condition);
|
$result = self::p($sql, $condition);
|
||||||
|
|
||||||
|
@ -1410,13 +1444,13 @@ class DBA
|
||||||
*/
|
*/
|
||||||
public static function count($table, array $condition = [])
|
public static function count($table, array $condition = [])
|
||||||
{
|
{
|
||||||
if ($table == '') {
|
if (empty($table)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$condition_string = self::buildCondition($condition);
|
$condition_string = self::buildCondition($condition);
|
||||||
|
|
||||||
$sql = "SELECT COUNT(*) AS `count` FROM `".$table."`".$condition_string;
|
$sql = "SELECT COUNT(*) AS `count` FROM " . self::formatTableName($table) . $condition_string;
|
||||||
|
|
||||||
$row = self::fetchFirst($sql, $condition);
|
$row = self::fetchFirst($sql, $condition);
|
||||||
|
|
||||||
|
@ -1507,6 +1541,15 @@ class DBA
|
||||||
*/
|
*/
|
||||||
public static function buildParameter(array $params = [])
|
public static function buildParameter(array $params = [])
|
||||||
{
|
{
|
||||||
|
$groupby_string = '';
|
||||||
|
if (isset($params['group_by'])) {
|
||||||
|
$groupby_string = " GROUP BY ";
|
||||||
|
foreach ($params['group_by'] as $fields) {
|
||||||
|
$groupby_string .= "`" . $fields . "`, ";
|
||||||
|
}
|
||||||
|
$groupby_string = substr($groupby_string, 0, -2);
|
||||||
|
}
|
||||||
|
|
||||||
$order_string = '';
|
$order_string = '';
|
||||||
if (isset($params['order'])) {
|
if (isset($params['order'])) {
|
||||||
$order_string = " ORDER BY ";
|
$order_string = " ORDER BY ";
|
||||||
|
@ -1531,7 +1574,7 @@ class DBA
|
||||||
$limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]);
|
$limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $order_string.$limit_string;
|
return $groupby_string . $order_string . $limit_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Friendica\Core\Config\Cache;
|
||||||
use Friendica\Database;
|
use Friendica\Database;
|
||||||
use Friendica\Util\Logger\VoidLogger;
|
use Friendica\Util\Logger\VoidLogger;
|
||||||
use Friendica\Util\Profiler;
|
use Friendica\Util\Profiler;
|
||||||
|
use ParagonIE\HiddenString\HiddenString;
|
||||||
|
|
||||||
class DBFactory
|
class DBFactory
|
||||||
{
|
{
|
||||||
|
@ -45,7 +46,7 @@ class DBFactory
|
||||||
} else {
|
} else {
|
||||||
$db_user = $server['MYSQL_USER'];
|
$db_user = $server['MYSQL_USER'];
|
||||||
}
|
}
|
||||||
$db_pass = (string) $server['MYSQL_PASSWORD'];
|
$db_pass = new HiddenString((string) $server['MYSQL_PASSWORD']);
|
||||||
$db_data = $server['MYSQL_DATABASE'];
|
$db_data = $server['MYSQL_DATABASE'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ class LoggerFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A list of classes, which shouldn't get logged
|
* A list of classes, which shouldn't get logged
|
||||||
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $ignoreClassList = [
|
private static $ignoreClassList = [
|
||||||
|
@ -37,8 +38,8 @@ class LoggerFactory
|
||||||
/**
|
/**
|
||||||
* Creates a new PSR-3 compliant logger instances
|
* Creates a new PSR-3 compliant logger instances
|
||||||
*
|
*
|
||||||
* @param string $channel The channel of the logger instance
|
* @param string $channel The channel of the logger instance
|
||||||
* @param Configuration $config The config
|
* @param Configuration $config The config
|
||||||
* @param Profiler $profiler The profiler of the app
|
* @param Profiler $profiler The profiler of the app
|
||||||
*
|
*
|
||||||
* @return LoggerInterface The PSR-3 compliant logger instance
|
* @return LoggerInterface The PSR-3 compliant logger instance
|
||||||
|
@ -55,8 +56,8 @@ class LoggerFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
$introspection = new Introspection(self::$ignoreClassList);
|
$introspection = new Introspection(self::$ignoreClassList);
|
||||||
$level = $config->get('system', 'loglevel');
|
$level = $config->get('system', 'loglevel');
|
||||||
$loglevel = self::mapLegacyConfigDebugLevel((string)$level);
|
$loglevel = self::mapLegacyConfigDebugLevel((string)$level);
|
||||||
|
|
||||||
switch ($config->get('system', 'logger_config', 'stream')) {
|
switch ($config->get('system', 'logger_config', 'stream')) {
|
||||||
case 'monolog':
|
case 'monolog':
|
||||||
|
@ -71,7 +72,10 @@ class LoggerFactory
|
||||||
|
|
||||||
$stream = $config->get('system', 'logfile');
|
$stream = $config->get('system', 'logfile');
|
||||||
|
|
||||||
static::addStreamHandler($logger, $stream, $loglevel);
|
// just add a stream in case it's either writable or not file
|
||||||
|
if (!is_file($stream) || is_writable($stream)) {
|
||||||
|
static::addStreamHandler($logger, $stream, $loglevel);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'syslog':
|
case 'syslog':
|
||||||
|
@ -81,7 +85,12 @@ class LoggerFactory
|
||||||
case 'stream':
|
case 'stream':
|
||||||
default:
|
default:
|
||||||
$stream = $config->get('system', 'logfile');
|
$stream = $config->get('system', 'logfile');
|
||||||
$logger = new StreamLogger($channel, $stream, $introspection, $loglevel);
|
// just add a stream in case it's either writable or not file
|
||||||
|
if (!is_file($stream) || is_writable($stream)) {
|
||||||
|
$logger = new StreamLogger($channel, $stream, $introspection, $loglevel);
|
||||||
|
} else {
|
||||||
|
$logger = new VoidLogger();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +114,8 @@ class LoggerFactory
|
||||||
*
|
*
|
||||||
* It should never get filled during normal usage of Friendica
|
* It should never get filled during normal usage of Friendica
|
||||||
*
|
*
|
||||||
* @param string $channel The channel of the logger instance
|
* @param string $channel The channel of the logger instance
|
||||||
* @param Configuration $config The config
|
* @param Configuration $config The config
|
||||||
* @param Profiler $profiler The profiler of the app
|
* @param Profiler $profiler The profiler of the app
|
||||||
*
|
*
|
||||||
* @return LoggerInterface The PSR-3 compliant logger instance
|
* @return LoggerInterface The PSR-3 compliant logger instance
|
||||||
|
@ -120,7 +129,8 @@ class LoggerFactory
|
||||||
$stream = $config->get('system', 'dlogfile');
|
$stream = $config->get('system', 'dlogfile');
|
||||||
$developerIp = $config->get('system', 'dlogip');
|
$developerIp = $config->get('system', 'dlogip');
|
||||||
|
|
||||||
if (!isset($developerIp) || !$debugging) {
|
if ((!isset($developerIp) || !$debugging) &&
|
||||||
|
(!is_file($stream) || is_writable($stream))) {
|
||||||
$logger = new VoidLogger();
|
$logger = new VoidLogger();
|
||||||
Logger::setDevLogger($logger);
|
Logger::setDevLogger($logger);
|
||||||
return $logger;
|
return $logger;
|
||||||
|
@ -149,7 +159,7 @@ class LoggerFactory
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'syslog':
|
case 'syslog':
|
||||||
$logger = new SyslogLogger($channel, $introspection, LogLevel::DEBUG);
|
$logger = new SyslogLogger($channel, $introspection, LogLevel::DEBUG);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'stream':
|
case 'stream':
|
||||||
|
@ -172,6 +182,7 @@ class LoggerFactory
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping a legacy level to the PSR-3 compliant levels
|
* Mapping a legacy level to the PSR-3 compliant levels
|
||||||
|
*
|
||||||
* @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
|
* @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel
|
||||||
*
|
*
|
||||||
* @param string $level the level to be mapped
|
* @param string $level the level to be mapped
|
||||||
|
@ -208,9 +219,9 @@ class LoggerFactory
|
||||||
/**
|
/**
|
||||||
* Adding a handler to a given logger instance
|
* Adding a handler to a given logger instance
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger The logger instance
|
* @param LoggerInterface $logger The logger instance
|
||||||
* @param mixed $stream The stream which handles the logger output
|
* @param mixed $stream The stream which handles the logger output
|
||||||
* @param string $level The level, for which this handler at least should handle logging
|
* @param string $level The level, for which this handler at least should handle logging
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Friendica\Model;
|
||||||
use Friendica\BaseObject;
|
use Friendica\BaseObject;
|
||||||
use Friendica\Content\Text\HTML;
|
use Friendica\Content\Text\HTML;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
use Friendica\Core\Config;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Protocol\ActivityPub;
|
use Friendica\Protocol\ActivityPub;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
|
@ -22,21 +23,30 @@ class APContact extends BaseObject
|
||||||
* Resolves the profile url from the address by using webfinger
|
* Resolves the profile url from the address by using webfinger
|
||||||
*
|
*
|
||||||
* @param string $addr profile address (user@domain.tld)
|
* @param string $addr profile address (user@domain.tld)
|
||||||
* @return string url
|
* @param string $url profile URL. When set then we return "true" when this profile url can be found at the address
|
||||||
|
* @return string|boolean url
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
private static function addrToUrl($addr)
|
private static function addrToUrl($addr, $url = null)
|
||||||
{
|
{
|
||||||
$addr_parts = explode('@', $addr);
|
$addr_parts = explode('@', $addr);
|
||||||
if (count($addr_parts) != 2) {
|
if (count($addr_parts) != 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$xrd_timeout = Config::get('system', 'xrd_timeout');
|
||||||
|
|
||||||
$webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr);
|
$webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr);
|
||||||
|
|
||||||
$curlResult = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']);
|
$curlResult = Network::curl($webfinger, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/jrd+json,application/json']);
|
||||||
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
||||||
return false;
|
$webfinger = Strings::normaliseLink($webfinger);
|
||||||
|
|
||||||
|
$curlResult = Network::curl($webfinger, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/jrd+json,application/json']);
|
||||||
|
|
||||||
|
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = json_decode($curlResult->getBody(), true);
|
$data = json_decode($curlResult->getBody(), true);
|
||||||
|
@ -46,11 +56,15 @@ class APContact extends BaseObject
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data['links'] as $link) {
|
foreach ($data['links'] as $link) {
|
||||||
|
if (!empty($url) && !empty($link['href']) && ($link['href'] == $url)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($link['href']) || empty($link['rel']) || empty($link['type'])) {
|
if (empty($link['href']) || empty($link['rel']) || empty($link['type'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($link['rel'] == 'self') && ($link['type'] == 'application/activity+json')) {
|
if (empty($url) && ($link['rel'] == 'self') && ($link['type'] == 'application/activity+json')) {
|
||||||
return $link['href'];
|
return $link['href'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +87,8 @@ class APContact extends BaseObject
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fetched_contact = false;
|
||||||
|
|
||||||
if (empty($update)) {
|
if (empty($update)) {
|
||||||
if (is_null($update)) {
|
if (is_null($update)) {
|
||||||
$ref_update = DateTimeFormat::utc('now - 1 month');
|
$ref_update = DateTimeFormat::utc('now - 1 month');
|
||||||
|
@ -96,24 +112,28 @@ class APContact extends BaseObject
|
||||||
if (!is_null($update)) {
|
if (!is_null($update)) {
|
||||||
return DBA::isResult($apcontact) ? $apcontact : false;
|
return DBA::isResult($apcontact) ? $apcontact : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DBA::isResult($apcontact)) {
|
||||||
|
$fetched_contact = $apcontact;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty(parse_url($url, PHP_URL_SCHEME))) {
|
if (empty(parse_url($url, PHP_URL_SCHEME))) {
|
||||||
$url = self::addrToUrl($url);
|
$url = self::addrToUrl($url);
|
||||||
if (empty($url)) {
|
if (empty($url)) {
|
||||||
return false;
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = ActivityPub::fetchContent($url);
|
$data = ActivityPub::fetchContent($url);
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
return false;
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
$compacted = JsonLD::compact($data);
|
$compacted = JsonLD::compact($data);
|
||||||
|
|
||||||
if (empty($compacted['@id'])) {
|
if (empty($compacted['@id'])) {
|
||||||
return false;
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
$apcontact = [];
|
$apcontact = [];
|
||||||
|
@ -152,8 +172,14 @@ class APContact extends BaseObject
|
||||||
$apcontact['alias'] = JsonLD::fetchElement($compacted['as:url'], 'as:href', '@id');
|
$apcontact['alias'] = JsonLD::fetchElement($compacted['as:url'], 'as:href', '@id');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($apcontact['url']) || empty($apcontact['inbox'])) {
|
// Quit if none of the basic values are set
|
||||||
return false;
|
if (empty($apcontact['url']) || empty($apcontact['inbox']) || empty($apcontact['type'])) {
|
||||||
|
return $fetched_contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quit if this doesn't seem to be an account at all
|
||||||
|
if (!in_array($apcontact['type'], ActivityPub::ACCOUNT_TYPES)) {
|
||||||
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
$parts = parse_url($apcontact['url']);
|
$parts = parse_url($apcontact['url']);
|
||||||
|
@ -183,11 +209,13 @@ class APContact extends BaseObject
|
||||||
// Unhandled from Kroeg
|
// Unhandled from Kroeg
|
||||||
// kroeg:blocks, updated
|
// kroeg:blocks, updated
|
||||||
|
|
||||||
// Check if the address is resolvable
|
$parts = parse_url($apcontact['url']);
|
||||||
if (self::addrToUrl($apcontact['addr']) == $apcontact['url']) {
|
unset($parts['path']);
|
||||||
$parts = parse_url($apcontact['url']);
|
$baseurl = Network::unparseURL($parts);
|
||||||
unset($parts['path']);
|
|
||||||
$apcontact['baseurl'] = Network::unparseURL($parts);
|
// Check if the address is resolvable or the profile url is identical with the base url of the system
|
||||||
|
if (self::addrToUrl($apcontact['addr'], $apcontact['url']) || Strings::compareLink($apcontact['url'], $baseurl)) {
|
||||||
|
$apcontact['baseurl'] = $baseurl;
|
||||||
} else {
|
} else {
|
||||||
$apcontact['addr'] = null;
|
$apcontact['addr'] = null;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +232,11 @@ class APContact extends BaseObject
|
||||||
|
|
||||||
DBA::update('apcontact', $apcontact, ['url' => $url], true);
|
DBA::update('apcontact', $apcontact, ['url' => $url], true);
|
||||||
|
|
||||||
|
// We delete the old entry when the URL is changed
|
||||||
|
if (($url != $apcontact['url']) && DBA::exists('apcontact', ['url' => $url]) && DBA::exists('apcontact', ['url' => $apcontact['url']])) {
|
||||||
|
DBA::delete('apcontact', ['url' => $url]);
|
||||||
|
}
|
||||||
|
|
||||||
// Update some data in the contact table with various ways to catch them all
|
// Update some data in the contact table with various ways to catch them all
|
||||||
$contact_fields = ['name' => $apcontact['name'], 'about' => $apcontact['about'], 'alias' => $apcontact['alias']];
|
$contact_fields = ['name' => $apcontact['name'], 'about' => $apcontact['about'], 'alias' => $apcontact['alias']];
|
||||||
|
|
||||||
|
@ -228,11 +261,13 @@ class APContact extends BaseObject
|
||||||
|
|
||||||
DBA::update('contact', $contact_fields, ['nurl' => Strings::normaliseLink($url)]);
|
DBA::update('contact', $contact_fields, ['nurl' => Strings::normaliseLink($url)]);
|
||||||
|
|
||||||
$contacts = DBA::select('contact', ['uid', 'id'], ['nurl' => Strings::normaliseLink($url)]);
|
if (!empty($apcontact['photo'])) {
|
||||||
while ($contact = DBA::fetch($contacts)) {
|
$contacts = DBA::select('contact', ['uid', 'id'], ['nurl' => Strings::normaliseLink($url)]);
|
||||||
Contact::updateAvatar($apcontact['photo'], $contact['uid'], $contact['id']);
|
while ($contact = DBA::fetch($contacts)) {
|
||||||
|
Contact::updateAvatar($apcontact['photo'], $contact['uid'], $contact['id']);
|
||||||
|
}
|
||||||
|
DBA::close($contacts);
|
||||||
}
|
}
|
||||||
DBA::close($contacts);
|
|
||||||
|
|
||||||
// Update the gcontact table
|
// Update the gcontact table
|
||||||
// These two fields don't exist in the gcontact table
|
// These two fields don't exist in the gcontact table
|
||||||
|
|
|
@ -124,6 +124,20 @@ class Contact extends BaseObject
|
||||||
return DBA::toArray($statement);
|
return DBA::toArray($statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $fields Array of selected fields, empty for all
|
||||||
|
* @param array $condition Array of fields for condition
|
||||||
|
* @param array $params Array of several parameters
|
||||||
|
* @return array
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function selectFirst(array $fields = [], array $condition = [], array $params = [])
|
||||||
|
{
|
||||||
|
$contact = DBA::selectFirst('contact', $fields, $condition, $params);
|
||||||
|
|
||||||
|
return $contact;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param integer $id Contact ID
|
* @param integer $id Contact ID
|
||||||
* @param array $fields Array of selected fields, empty for all
|
* @param array $fields Array of selected fields, empty for all
|
||||||
|
@ -579,11 +593,13 @@ class Contact extends BaseObject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$file_suffix = 'jpg';
|
||||||
|
|
||||||
$fields = ['name' => $profile['name'], 'nick' => $user['nickname'],
|
$fields = ['name' => $profile['name'], 'nick' => $user['nickname'],
|
||||||
'avatar-date' => $self['avatar-date'], 'location' => Profile::formatLocation($profile),
|
'avatar-date' => $self['avatar-date'], 'location' => Profile::formatLocation($profile),
|
||||||
'about' => $profile['about'], 'keywords' => $profile['pub_keywords'],
|
'about' => $profile['about'], 'keywords' => $profile['pub_keywords'],
|
||||||
'gender' => $profile['gender'], 'avatar' => $profile['photo'],
|
'gender' => $profile['gender'], 'contact-type' => $user['account-type'],
|
||||||
'contact-type' => $user['account-type'], 'xmpp' => $profile['xmpp']];
|
'xmpp' => $profile['xmpp']];
|
||||||
|
|
||||||
$avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]);
|
$avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]);
|
||||||
if (DBA::isResult($avatar)) {
|
if (DBA::isResult($avatar)) {
|
||||||
|
@ -595,8 +611,6 @@ class Contact extends BaseObject
|
||||||
$types = Image::supportedTypes();
|
$types = Image::supportedTypes();
|
||||||
if (isset($types[$avatar['type']])) {
|
if (isset($types[$avatar['type']])) {
|
||||||
$file_suffix = $types[$avatar['type']];
|
$file_suffix = $types[$avatar['type']];
|
||||||
} else {
|
|
||||||
$file_suffix = 'jpg';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are adding a timestamp value so that other systems won't use cached content
|
// We are adding a timestamp value so that other systems won't use cached content
|
||||||
|
@ -615,6 +629,7 @@ class Contact extends BaseObject
|
||||||
$fields['micro'] = System::baseUrl() . '/images/person-48.jpg';
|
$fields['micro'] = System::baseUrl() . '/images/person-48.jpg';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fields['avatar'] = System::baseUrl() . '/photo/profile/' .$uid . '.' . $file_suffix;
|
||||||
$fields['forum'] = $user['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
|
$fields['forum'] = $user['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
|
||||||
$fields['prv'] = $user['page-flags'] == User::PAGE_FLAGS_PRVGROUP;
|
$fields['prv'] = $user['page-flags'] == User::PAGE_FLAGS_PRVGROUP;
|
||||||
|
|
||||||
|
@ -647,8 +662,8 @@ class Contact extends BaseObject
|
||||||
DBA::update('contact', $fields, ['uid' => 0, 'nurl' => $self['nurl']]);
|
DBA::update('contact', $fields, ['uid' => 0, 'nurl' => $self['nurl']]);
|
||||||
|
|
||||||
// Update the profile
|
// Update the profile
|
||||||
$fields = ['photo' => System::baseUrl() . '/photo/profile/' .$uid . '.jpg',
|
$fields = ['photo' => System::baseUrl() . '/photo/profile/' .$uid . '.' . $file_suffix,
|
||||||
'thumb' => System::baseUrl() . '/photo/avatar/' . $uid .'.jpg'];
|
'thumb' => System::baseUrl() . '/photo/avatar/' . $uid .'.' . $file_suffix];
|
||||||
DBA::update('profile', $fields, ['uid' => $uid, 'is-default' => true]);
|
DBA::update('profile', $fields, ['uid' => $uid, 'is-default' => true]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -894,7 +909,7 @@ class Contact extends BaseObject
|
||||||
// If there is more than one entry we filter out the connector networks
|
// If there is more than one entry we filter out the connector networks
|
||||||
if (count($r) > 1) {
|
if (count($r) > 1) {
|
||||||
foreach ($r as $id => $result) {
|
foreach ($r as $id => $result) {
|
||||||
if ($result["network"] == Protocol::STATUSNET) {
|
if (!in_array($result["network"], Protocol::NATIVE_SUPPORT)) {
|
||||||
unset($r[$id]);
|
unset($r[$id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1078,7 +1093,7 @@ class Contact extends BaseObject
|
||||||
$profile_link = $profile_link . '?tab=profile';
|
$profile_link = $profile_link . '?tab=profile';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA]) && !$contact['self']) {
|
if (self::canReceivePrivateMessages($contact)) {
|
||||||
$pm_url = System::baseUrl() . '/message/new/' . $contact['id'];
|
$pm_url = System::baseUrl() . '/message/new/' . $contact['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,12 +1464,14 @@ class Contact extends BaseObject
|
||||||
return $contact_id;
|
return $contact_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$updated = ['addr' => $data['addr'],
|
$updated = [
|
||||||
|
'addr' => $data['addr'] ?? '',
|
||||||
'alias' => defaults($data, 'alias', ''),
|
'alias' => defaults($data, 'alias', ''),
|
||||||
'url' => $data['url'],
|
'url' => $data['url'],
|
||||||
'nurl' => Strings::normaliseLink($data['url']),
|
'nurl' => Strings::normaliseLink($data['url']),
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'nick' => $data['nick']];
|
'nick' => $data['nick']
|
||||||
|
];
|
||||||
|
|
||||||
if (!empty($data['keywords'])) {
|
if (!empty($data['keywords'])) {
|
||||||
$updated['keywords'] = $data['keywords'];
|
$updated['keywords'] = $data['keywords'];
|
||||||
|
@ -1488,7 +1505,7 @@ class Contact extends BaseObject
|
||||||
$updated['pubkey'] = $data['pubkey'];
|
$updated['pubkey'] = $data['pubkey'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($data['addr'] != $contact['addr']) || (!empty($data['alias']) && ($data['alias'] != $contact['alias']))) {
|
if (($updated['addr'] != $contact['addr']) || (!empty($data['alias']) && ($data['alias'] != $contact['alias']))) {
|
||||||
$updated['uri-date'] = DateTimeFormat::utcNow();
|
$updated['uri-date'] = DateTimeFormat::utcNow();
|
||||||
}
|
}
|
||||||
if (($data["name"] != $contact["name"]) || ($data["nick"] != $contact["nick"])) {
|
if (($data["name"] != $contact["name"]) || ($data["nick"] != $contact["nick"])) {
|
||||||
|
@ -1709,7 +1726,7 @@ class Contact extends BaseObject
|
||||||
*/
|
*/
|
||||||
public static function updateAvatar($avatar, $uid, $cid, $force = false)
|
public static function updateAvatar($avatar, $uid, $cid, $force = false)
|
||||||
{
|
{
|
||||||
$contact = DBA::selectFirst('contact', ['avatar', 'photo', 'thumb', 'micro', 'nurl'], ['id' => $cid]);
|
$contact = DBA::selectFirst('contact', ['avatar', 'photo', 'thumb', 'micro', 'nurl'], ['id' => $cid, 'self' => false]);
|
||||||
if (!DBA::isResult($contact)) {
|
if (!DBA::isResult($contact)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1720,17 +1737,14 @@ class Contact extends BaseObject
|
||||||
$photos = Photo::importProfilePhoto($avatar, $uid, $cid, true);
|
$photos = Photo::importProfilePhoto($avatar, $uid, $cid, true);
|
||||||
|
|
||||||
if ($photos) {
|
if ($photos) {
|
||||||
DBA::update(
|
$fields = ['avatar' => $avatar, 'photo' => $photos[0], 'thumb' => $photos[1], 'micro' => $photos[2], 'avatar-date' => DateTimeFormat::utcNow()];
|
||||||
'contact',
|
DBA::update('contact', $fields, ['id' => $cid]);
|
||||||
['avatar' => $avatar, 'photo' => $photos[0], 'thumb' => $photos[1], 'micro' => $photos[2], 'avatar-date' => DateTimeFormat::utcNow()],
|
|
||||||
['id' => $cid]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update the public contact (contact id = 0)
|
// Update the public contact (contact id = 0)
|
||||||
if ($uid != 0) {
|
if ($uid != 0) {
|
||||||
$pcontact = DBA::selectFirst('contact', ['id'], ['nurl' => $contact['nurl'], 'uid' => 0]);
|
$pcontact = DBA::selectFirst('contact', ['id'], ['nurl' => $contact['nurl'], 'uid' => 0]);
|
||||||
if (DBA::isResult($pcontact)) {
|
if (DBA::isResult($pcontact)) {
|
||||||
self::updateAvatar($avatar, 0, $pcontact['id'], $force);
|
DBA::update('contact', $fields, ['id' => $pcontact['id']]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2120,63 +2134,81 @@ class Contact extends BaseObject
|
||||||
return $contact;
|
return $contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function addRelationship($importer, $contact, $datarray, $item = '', $sharing = false, $note = '') {
|
/**
|
||||||
|
* @param array $importer Owner (local user) data
|
||||||
|
* @param array $contact Existing owner-specific contact data we want to expand the relationship with. Optional.
|
||||||
|
* @param array $datarray An item-like array with at least the 'author-id' and 'author-url' keys for the contact. Mandatory.
|
||||||
|
* @param bool $sharing True: Contact is now sharing with Owner; False: Contact is now following Owner (default)
|
||||||
|
* @param string $note Introduction additional message
|
||||||
|
* @return bool|null True: follow request is accepted; False: relationship is rejected; Null: relationship is pending
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
public static function addRelationship(array $importer, array $contact, array $datarray, $sharing = false, $note = '')
|
||||||
|
{
|
||||||
// Should always be set
|
// Should always be set
|
||||||
if (empty($datarray['author-id'])) {
|
if (empty($datarray['author-id'])) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = ['url', 'name', 'nick', 'photo', 'network'];
|
$fields = ['url', 'name', 'nick', 'avatar', 'photo', 'network', 'blocked'];
|
||||||
$pub_contact = DBA::selectFirst('contact', $fields, ['id' => $datarray['author-id']]);
|
$pub_contact = DBA::selectFirst('contact', $fields, ['id' => $datarray['author-id']]);
|
||||||
if (!DBA::isResult($pub_contact)) {
|
if (!DBA::isResult($pub_contact)) {
|
||||||
// Should never happen
|
// Should never happen
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contact is blocked at node-level
|
||||||
|
if (self::isBlocked($datarray['author-id'])) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = defaults($datarray, 'author-link', $pub_contact['url']);
|
$url = defaults($datarray, 'author-link', $pub_contact['url']);
|
||||||
$name = $pub_contact['name'];
|
$name = $pub_contact['name'];
|
||||||
$photo = $pub_contact['photo'];
|
$photo = defaults($pub_contact, 'avatar', $pub_contact["photo"]);
|
||||||
$nick = $pub_contact['nick'];
|
$nick = $pub_contact['nick'];
|
||||||
$network = $pub_contact['network'];
|
$network = $pub_contact['network'];
|
||||||
|
|
||||||
if (is_array($contact)) {
|
if (!empty($contact)) {
|
||||||
|
// Contact is blocked at user-level
|
||||||
|
if (!empty($contact['id']) && !empty($importer['id']) &&
|
||||||
|
self::isBlockedByUser($contact['id'], $importer['id'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the existing contact isn't archived
|
// Make sure that the existing contact isn't archived
|
||||||
self::unmarkForArchival($contact);
|
self::unmarkForArchival($contact);
|
||||||
|
|
||||||
$protocol = self::getProtocol($url, $contact['network']);
|
|
||||||
|
|
||||||
if (($contact['rel'] == self::SHARING)
|
if (($contact['rel'] == self::SHARING)
|
||||||
|| ($sharing && $contact['rel'] == self::FOLLOWER)) {
|
|| ($sharing && $contact['rel'] == self::FOLLOWER)) {
|
||||||
DBA::update('contact', ['rel' => self::FRIEND, 'writable' => true, 'pending' => false],
|
DBA::update('contact', ['rel' => self::FRIEND, 'writable' => true, 'pending' => false],
|
||||||
['id' => $contact['id'], 'uid' => $importer['uid']]);
|
['id' => $contact['id'], 'uid' => $importer['uid']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($protocol == Protocol::ACTIVITYPUB) {
|
return true;
|
||||||
ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send email notification to owner?
|
|
||||||
} else {
|
} else {
|
||||||
$protocol = self::getProtocol($url, $network);
|
// send email notification to owner?
|
||||||
|
|
||||||
if (DBA::exists('contact', ['nurl' => Strings::normaliseLink($url), 'uid' => $importer['uid'], 'pending' => true])) {
|
if (DBA::exists('contact', ['nurl' => Strings::normaliseLink($url), 'uid' => $importer['uid'], 'pending' => true])) {
|
||||||
Logger::log('ignoring duplicated connection request from pending contact ' . $url);
|
Logger::log('ignoring duplicated connection request from pending contact ' . $url);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create contact record
|
// create contact record
|
||||||
q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
|
DBA::insert('contact', [
|
||||||
`blocked`, `readonly`, `pending`, `writable`)
|
'uid' => $importer['uid'],
|
||||||
VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, 1)",
|
'created' => DateTimeFormat::utcNow(),
|
||||||
intval($importer['uid']),
|
'url' => $url,
|
||||||
DBA::escape(DateTimeFormat::utcNow()),
|
'nurl' => Strings::normaliseLink($url),
|
||||||
DBA::escape($url),
|
'name' => $name,
|
||||||
DBA::escape(Strings::normaliseLink($url)),
|
'nick' => $nick,
|
||||||
DBA::escape($name),
|
'photo' => $photo,
|
||||||
DBA::escape($nick),
|
'network' => $network,
|
||||||
DBA::escape($photo),
|
'rel' => self::FOLLOWER,
|
||||||
DBA::escape($network),
|
'blocked' => 0,
|
||||||
intval(self::FOLLOWER)
|
'readonly' => 0,
|
||||||
);
|
'pending' => 1,
|
||||||
|
'writable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
$contact_record = [
|
$contact_record = [
|
||||||
'id' => DBA::lastInsertId(),
|
'id' => DBA::lastInsertId(),
|
||||||
|
@ -2220,20 +2252,16 @@ class Contact extends BaseObject
|
||||||
'verb' => ($sharing ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW),
|
'verb' => ($sharing ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW),
|
||||||
'otype' => 'intro'
|
'otype' => 'intro'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
} elseif (DBA::isResult($user) && in_array($user['page-flags'], [User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE, User::PAGE_FLAGS_COMMUNITY])) {
|
} elseif (DBA::isResult($user) && in_array($user['page-flags'], [User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE, User::PAGE_FLAGS_COMMUNITY])) {
|
||||||
$condition = ['uid' => $importer['uid'], 'url' => $url, 'pending' => true];
|
$condition = ['uid' => $importer['uid'], 'url' => $url, 'pending' => true];
|
||||||
DBA::update('contact', ['pending' => false], $condition);
|
DBA::update('contact', ['pending' => false], $condition);
|
||||||
|
|
||||||
$contact = DBA::selectFirst('contact', ['url', 'network', 'hub-verify'], ['id' => $contact_record['id']]);
|
return true;
|
||||||
$protocol = self::getProtocol($contact['url'], $contact['network']);
|
|
||||||
|
|
||||||
if ($protocol == Protocol::ACTIVITYPUB) {
|
|
||||||
ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function removeFollower($importer, $contact, array $datarray = [], $item = "")
|
public static function removeFollower($importer, $contact, array $datarray = [], $item = "")
|
||||||
|
@ -2342,6 +2370,9 @@ class Contact extends BaseObject
|
||||||
return $url ?: $contact_url; // Equivalent to: ($url != '') ? $url : $contact_url;
|
return $url ?: $contact_url; // Equivalent to: ($url != '') ? $url : $contact_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevents endless loop in case only a non-public contact exists for the contact URL
|
||||||
|
unset($data['uid']);
|
||||||
|
|
||||||
return self::magicLinkByContact($data, $contact_url);
|
return self::magicLinkByContact($data, $contact_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2431,4 +2462,18 @@ class Contact extends BaseObject
|
||||||
// Is it a forum?
|
// Is it a forum?
|
||||||
return ($contact['forum'] || $contact['prv']);
|
return ($contact['forum'] || $contact['prv']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the remote contact receive private messages?
|
||||||
|
*
|
||||||
|
* @param array $contact
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function canReceivePrivateMessages(array $contact)
|
||||||
|
{
|
||||||
|
$protocol = $contact['network'] ?? $contact['protocol'] ?? Protocol::PHANTOM;
|
||||||
|
$self = $contact['self'] ?? false;
|
||||||
|
|
||||||
|
return in_array($protocol, [Protocol::DFRN, Protocol::DIASPORA, Protocol::ACTIVITYPUB]) && !$self;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ class Event extends BaseObject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBA::delete('event', ['id' => $event_id]);
|
DBA::delete('event', ['id' => $event_id], ['cascade' => false]);
|
||||||
Logger::log("Deleted event ".$event_id, Logger::DEBUG);
|
Logger::log("Deleted event ".$event_id, Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,127 +11,149 @@ use Friendica\Database\DBA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class handles FileTag related functions
|
* @brief This class handles FileTag related functions
|
||||||
|
*
|
||||||
|
* post categories and "save to file" use the same item.file table for storage.
|
||||||
|
* We will differentiate the different uses by wrapping categories in angle brackets
|
||||||
|
* and save to file categories in square brackets.
|
||||||
|
* To do this we need to escape these characters if they appear in our tag.
|
||||||
*/
|
*/
|
||||||
class FileTag
|
class FileTag
|
||||||
{
|
{
|
||||||
// post categories and "save to file" use the same item.file table for storage.
|
/**
|
||||||
// We will differentiate the different uses by wrapping categories in angle brackets
|
* @brief URL encode <, >, left and right brackets
|
||||||
// and save to file categories in square brackets.
|
*
|
||||||
// To do this we need to escape these characters if they appear in our tag.
|
* @param string $s String to be URL encoded.
|
||||||
|
*
|
||||||
|
* @return string The URL encoded string.
|
||||||
|
*/
|
||||||
|
public static function encode($s)
|
||||||
|
{
|
||||||
|
return str_replace(['<', '>', '[', ']'], ['%3c', '%3e', '%5b', '%5d'], $s);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief URL encode <, >, left and right brackets
|
* @brief URL decode <, >, left and right brackets
|
||||||
*
|
*
|
||||||
* @param string $s String to be URL encoded.
|
* @param string $s The URL encoded string to be decoded
|
||||||
*
|
*
|
||||||
* @return string The URL encoded string.
|
* @return string The decoded string.
|
||||||
*/
|
*/
|
||||||
public static function encode($s)
|
public static function decode($s)
|
||||||
{
|
{
|
||||||
return str_replace(['<', '>', '[', ']'], ['%3c', '%3e', '%5b', '%5d'], $s);
|
return str_replace(['%3c', '%3e', '%5b', '%5d'], ['<', '>', '[', ']'], $s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief URL decode <, >, left and right brackets
|
* @brief Query files for tag
|
||||||
*
|
*
|
||||||
* @param string $s The URL encoded string to be decoded
|
* @param string $table The table to be queired.
|
||||||
*
|
* @param string $s The search term
|
||||||
* @return string The decoded string.
|
* @param string $type Optional file type.
|
||||||
*/
|
*
|
||||||
public static function decode($s)
|
* @return string Query string.
|
||||||
{
|
*/
|
||||||
return str_replace(['%3c', '%3e', '%5b', '%5d'], ['<', '>', '[', ']'], $s);
|
public static function fileQuery($table, $s, $type = 'file')
|
||||||
}
|
{
|
||||||
|
if ($type == 'file') {
|
||||||
|
$str = preg_quote('[' . str_replace('%', '%%', self::encode($s)) . ']');
|
||||||
|
} else {
|
||||||
|
$str = preg_quote('<' . str_replace('%', '%%', self::encode($s)) . '>');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return " AND " . (($table) ? DBA::escape($table) . '.' : '') . "file regexp '" . DBA::escape($str) . "' ";
|
||||||
* @brief Query files for tag
|
}
|
||||||
*
|
|
||||||
* @param string $table The table to be queired.
|
|
||||||
* @param string $s The search term
|
|
||||||
* @param string $type Optional file type.
|
|
||||||
*
|
|
||||||
* @return string Query string.
|
|
||||||
*/
|
|
||||||
public static function fileQuery($table, $s, $type = 'file')
|
|
||||||
{
|
|
||||||
if ($type == 'file') {
|
|
||||||
$str = preg_quote('[' . str_replace('%', '%%', self::encode($s)) . ']');
|
|
||||||
} else {
|
|
||||||
$str = preg_quote('<' . str_replace('%', '%%', self::encode($s)) . '>');
|
|
||||||
}
|
|
||||||
|
|
||||||
return " AND " . (($table) ? DBA::escape($table) . '.' : '') . "file regexp '" . DBA::escape($str) . "' ";
|
/**
|
||||||
}
|
* Get file tags from array
|
||||||
|
*
|
||||||
|
* ex. given [music,video] return <music><video> or [music][video]
|
||||||
|
*
|
||||||
|
* @param array $array A list of tags.
|
||||||
|
* @param string $type Optional file type.
|
||||||
|
*
|
||||||
|
* @return string A list of file tags.
|
||||||
|
*/
|
||||||
|
public static function arrayToFile(array $array, string $type = 'file')
|
||||||
|
{
|
||||||
|
$tag_list = '';
|
||||||
|
if ($type == 'file') {
|
||||||
|
$lbracket = '[';
|
||||||
|
$rbracket = ']';
|
||||||
|
} else {
|
||||||
|
$lbracket = '<';
|
||||||
|
$rbracket = '>';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
foreach ($array as $item) {
|
||||||
* @brief Get file tags from list
|
if (strlen($item)) {
|
||||||
*
|
$tag_list .= $lbracket . self::encode(trim($item)) . $rbracket;
|
||||||
* ex. given music,video return <music><video> or [music][video]
|
}
|
||||||
* @param string $list A comma delimited list of tags.
|
}
|
||||||
* @param string $type Optional file type.
|
|
||||||
*
|
|
||||||
* @return string A list of file tags.
|
|
||||||
*/
|
|
||||||
public static function listToFile($list, $type = 'file')
|
|
||||||
{
|
|
||||||
$tag_list = '';
|
|
||||||
if (strlen($list)) {
|
|
||||||
$list_array = explode(",", $list);
|
|
||||||
if ($type == 'file') {
|
|
||||||
$lbracket = '[';
|
|
||||||
$rbracket = ']';
|
|
||||||
} else {
|
|
||||||
$lbracket = '<';
|
|
||||||
$rbracket = '>';
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($list_array as $item)
|
return $tag_list;
|
||||||
{
|
}
|
||||||
if (strlen($item))
|
|
||||||
{
|
|
||||||
$tag_list .= $lbracket . self::encode(trim($item)) . $rbracket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tag_list;
|
/**
|
||||||
}
|
* Get tag list from file tags
|
||||||
|
*
|
||||||
|
* ex. given <music><video>[friends], return [music,video] or [friends]
|
||||||
|
*
|
||||||
|
* @param string $file File tags
|
||||||
|
* @param string $type Optional file type.
|
||||||
|
*
|
||||||
|
* @return array List of tag names.
|
||||||
|
*/
|
||||||
|
public static function fileToArray(string $file, string $type = 'file')
|
||||||
|
{
|
||||||
|
$matches = [];
|
||||||
|
$return = [];
|
||||||
|
|
||||||
/**
|
if ($type == 'file') {
|
||||||
* @brief Get list from file tags
|
$cnt = preg_match_all('/\[(.*?)\]/', $file, $matches, PREG_SET_ORDER);
|
||||||
*
|
} else {
|
||||||
* ex. given <music><video>[friends], return music,video or friends
|
$cnt = preg_match_all('/<(.*?)>/', $file, $matches, PREG_SET_ORDER);
|
||||||
* @param string $file File tags
|
}
|
||||||
* @param string $type Optional file type.
|
|
||||||
*
|
|
||||||
* @return string Comma delimited list of tag names.
|
|
||||||
*/
|
|
||||||
public static function fileToList($file, $type = 'file')
|
|
||||||
{
|
|
||||||
$matches = false;
|
|
||||||
$list = '';
|
|
||||||
|
|
||||||
if ($type == 'file') {
|
if ($cnt) {
|
||||||
$cnt = preg_match_all('/\[(.*?)\]/', $file, $matches, PREG_SET_ORDER);
|
foreach ($matches as $match) {
|
||||||
} else {
|
$return[] = self::decode($match[1]);
|
||||||
$cnt = preg_match_all('/<(.*?)>/', $file, $matches, PREG_SET_ORDER);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cnt)
|
return $return;
|
||||||
{
|
}
|
||||||
foreach ($matches as $mtch)
|
|
||||||
{
|
|
||||||
if (strlen($list))
|
|
||||||
{
|
|
||||||
$list .= ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
$list .= self::decode($mtch[1]);
|
/**
|
||||||
}
|
* @brief Get file tags from list
|
||||||
}
|
*
|
||||||
|
* ex. given music,video return <music><video> or [music][video]
|
||||||
|
* @param string $list A comma delimited list of tags.
|
||||||
|
* @param string $type Optional file type.
|
||||||
|
*
|
||||||
|
* @return string A list of file tags.
|
||||||
|
* @deprecated since 2019.06 use arrayToFile() instead
|
||||||
|
*/
|
||||||
|
public static function listToFile(string $list, string $type = 'file')
|
||||||
|
{
|
||||||
|
$list_array = explode(',', $list);
|
||||||
|
|
||||||
return $list;
|
return self::arrayToFile($list_array, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get list from file tags
|
||||||
|
*
|
||||||
|
* ex. given <music><video>[friends], return music,video or friends
|
||||||
|
* @param string $file File tags
|
||||||
|
* @param string $type Optional file type.
|
||||||
|
*
|
||||||
|
* @return string Comma delimited list of tag names.
|
||||||
|
* @deprecated since 2019.06 use fileToArray() instead
|
||||||
|
*/
|
||||||
|
public static function fileToList(string $file, $type = 'file')
|
||||||
|
{
|
||||||
|
return implode(',', self::fileToArray($file, $type));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update file tags in PConfig
|
* @brief Update file tags in PConfig
|
||||||
|
@ -142,83 +164,74 @@ class FileTag
|
||||||
* @param string $type Optional file type.
|
* @param string $type Optional file type.
|
||||||
*
|
*
|
||||||
* @return boolean A value indicating success or failure.
|
* @return boolean A value indicating success or failure.
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function updatePconfig($uid, $file_old, $file_new, $type = 'file')
|
public static function updatePconfig(int $uid, string $file_old, string $file_new, string $type = 'file')
|
||||||
{
|
{
|
||||||
if (!intval($uid)) {
|
if (!intval($uid)) {
|
||||||
return false;
|
return false;
|
||||||
} elseif ($file_old == $file_new) {
|
} elseif ($file_old == $file_new) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$saved = PConfig::get($uid, 'system', 'filetags');
|
$saved = PConfig::get($uid, 'system', 'filetags');
|
||||||
|
|
||||||
if (strlen($saved))
|
if (strlen($saved)) {
|
||||||
{
|
if ($type == 'file') {
|
||||||
if ($type == 'file') {
|
$lbracket = '[';
|
||||||
$lbracket = '[';
|
$rbracket = ']';
|
||||||
$rbracket = ']';
|
$termtype = TERM_FILE;
|
||||||
$termtype = TERM_FILE;
|
} else {
|
||||||
} else {
|
$lbracket = '<';
|
||||||
$lbracket = '<';
|
$rbracket = '>';
|
||||||
$rbracket = '>';
|
$termtype = TERM_CATEGORY;
|
||||||
$termtype = TERM_CATEGORY;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$filetags_updated = $saved;
|
$filetags_updated = $saved;
|
||||||
|
|
||||||
// check for new tags to be added as filetags in pconfig
|
// check for new tags to be added as filetags in pconfig
|
||||||
$new_tags = [];
|
$new_tags = [];
|
||||||
$check_new_tags = explode(",", self::fileToList($file_new, $type));
|
foreach (self::fileToArray($file_new, $type) as $tag) {
|
||||||
|
if (!stristr($saved, $lbracket . self::encode($tag) . $rbracket)) {
|
||||||
|
$new_tags[] = $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($check_new_tags as $tag)
|
$filetags_updated .= self::arrayToFile($new_tags, $type);
|
||||||
{
|
|
||||||
if (!stristr($saved,$lbracket . self::encode($tag) . $rbracket)) {
|
|
||||||
$new_tags[] = $tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$filetags_updated .= self::listToFile(implode(",", $new_tags), $type);
|
// check for deleted tags to be removed from filetags in pconfig
|
||||||
|
$deleted_tags = [];
|
||||||
|
foreach (self::fileToArray($file_old, $type) as $tag) {
|
||||||
|
if (!stristr($file_new, $lbracket . self::encode($tag) . $rbracket)) {
|
||||||
|
$deleted_tags[] = $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check for deleted tags to be removed from filetags in pconfig
|
foreach ($deleted_tags as $key => $tag) {
|
||||||
$deleted_tags = [];
|
$r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
|
||||||
$check_deleted_tags = explode(",", self::fileToList($file_old, $type));
|
DBA::escape($tag),
|
||||||
|
intval(Term::OBJECT_TYPE_POST),
|
||||||
|
intval($termtype),
|
||||||
|
intval($uid));
|
||||||
|
|
||||||
foreach ($check_deleted_tags as $tag)
|
if (DBA::isResult($r)) {
|
||||||
{
|
unset($deleted_tags[$key]);
|
||||||
if (!stristr($file_new,$lbracket . self::encode($tag) . $rbracket)) {
|
} else {
|
||||||
$deleted_tags[] = $tag;
|
$filetags_updated = str_replace($lbracket . self::encode($tag) . $rbracket, '', $filetags_updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($deleted_tags as $key => $tag)
|
if ($saved != $filetags_updated) {
|
||||||
{
|
PConfig::set($uid, 'system', 'filetags', $filetags_updated);
|
||||||
$r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
|
}
|
||||||
DBA::escape($tag),
|
|
||||||
intval(TERM_OBJ_POST),
|
|
||||||
intval($termtype),
|
|
||||||
intval($uid));
|
|
||||||
|
|
||||||
if (DBA::isResult($r)) {
|
return true;
|
||||||
unset($deleted_tags[$key]);
|
} elseif (strlen($file_new)) {
|
||||||
} else {
|
PConfig::set($uid, 'system', 'filetags', $file_new);
|
||||||
$filetags_updated = str_replace($lbracket . self::encode($tag) . $rbracket, '', $filetags_updated);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($saved != $filetags_updated)
|
return true;
|
||||||
{
|
}
|
||||||
PConfig::set($uid, 'system', 'filetags', $filetags_updated);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} elseif (strlen($file_new)) {
|
|
||||||
PConfig::set($uid, 'system', 'filetags', $file_new);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add tag to file
|
* @brief Add tag to file
|
||||||
|
@ -230,34 +243,30 @@ class FileTag
|
||||||
* @return boolean A value indicating success or failure.
|
* @return boolean A value indicating success or failure.
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function saveFile($uid, $item_id, $file)
|
public static function saveFile($uid, $item_id, $file)
|
||||||
{
|
{
|
||||||
if (!intval($uid))
|
if (!intval($uid)) {
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
|
$item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
|
||||||
if (DBA::isResult($item))
|
if (DBA::isResult($item)) {
|
||||||
{
|
if (!stristr($item['file'], '[' . self::encode($file) . ']')) {
|
||||||
if (!stristr($item['file'], '[' . self::encode($file) . ']'))
|
$fields = ['file' => $item['file'] . '[' . self::encode($file) . ']'];
|
||||||
{
|
Item::update($fields, ['id' => $item_id]);
|
||||||
$fields = ['file' => $item['file'] . '[' . self::encode($file) . ']'];
|
}
|
||||||
Item::update($fields, ['id' => $item_id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$saved = PConfig::get($uid, 'system', 'filetags');
|
$saved = PConfig::get($uid, 'system', 'filetags');
|
||||||
|
|
||||||
if (!strlen($saved) || !stristr($saved, '[' . self::encode($file) . ']'))
|
if (!strlen($saved) || !stristr($saved, '[' . self::encode($file) . ']')) {
|
||||||
{
|
PConfig::set($uid, 'system', 'filetags', $saved . '[' . self::encode($file) . ']');
|
||||||
PConfig::set($uid, 'system', 'filetags', $saved . '[' . self::encode($file) . ']');
|
}
|
||||||
}
|
|
||||||
|
|
||||||
info(L10n::t('Item filed'));
|
info(L10n::t('Item filed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove tag from file
|
* @brief Remove tag from file
|
||||||
|
@ -270,45 +279,42 @@ class FileTag
|
||||||
* @return boolean A value indicating success or failure.
|
* @return boolean A value indicating success or failure.
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function unsaveFile($uid, $item_id, $file, $cat = false)
|
public static function unsaveFile($uid, $item_id, $file, $cat = false)
|
||||||
{
|
{
|
||||||
if (!intval($uid))
|
if (!intval($uid)) {
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($cat == true) {
|
if ($cat == true) {
|
||||||
$pattern = '<' . self::encode($file) . '>';
|
$pattern = '<' . self::encode($file) . '>';
|
||||||
$termtype = TERM_CATEGORY;
|
$termtype = Term::CATEGORY;
|
||||||
} else {
|
} else {
|
||||||
$pattern = '[' . self::encode($file) . ']';
|
$pattern = '[' . self::encode($file) . ']';
|
||||||
$termtype = TERM_FILE;
|
$termtype = Term::FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
|
$item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
|
||||||
|
|
||||||
if (!DBA::isResult($item))
|
if (!DBA::isResult($item)) {
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$fields = ['file' => str_replace($pattern, '', $item['file'])];
|
$fields = ['file' => str_replace($pattern, '', $item['file'])];
|
||||||
|
|
||||||
Item::update($fields, ['id' => $item_id]);
|
Item::update($fields, ['id' => $item_id]);
|
||||||
|
|
||||||
$r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
|
$r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
|
||||||
DBA::escape($file),
|
DBA::escape($file),
|
||||||
intval(TERM_OBJ_POST),
|
intval(Term::OBJECT_TYPE_POST),
|
||||||
intval($termtype),
|
intval($termtype),
|
||||||
intval($uid)
|
intval($uid)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!DBA::isResult($r))
|
if (!DBA::isResult($r)) {
|
||||||
{
|
$saved = PConfig::get($uid, 'system', 'filetags');
|
||||||
$saved = PConfig::get($uid, 'system', 'filetags');
|
PConfig::set($uid, 'system', 'filetags', str_replace($pattern, '', $saved));
|
||||||
PConfig::set($uid, 'system', 'filetags', str_replace($pattern, '', $saved));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Content\Text\HTML;
|
use Friendica\Content\Text\HTML;
|
||||||
use Friendica\Core\Config;
|
use Friendica\Core\Config;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
|
use Friendica\Core\L10n;
|
||||||
use Friendica\Core\Lock;
|
use Friendica\Core\Lock;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\L10n;
|
|
||||||
use Friendica\Core\PConfig;
|
use Friendica\Core\PConfig;
|
||||||
use Friendica\Core\Protocol;
|
use Friendica\Core\Protocol;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
|
@ -24,10 +24,11 @@ use Friendica\Protocol\Diaspora;
|
||||||
use Friendica\Protocol\OStatus;
|
use Friendica\Protocol\OStatus;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Map;
|
use Friendica\Util\Map;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Security;
|
use Friendica\Util\Security;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\XML;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
use Text_LanguageDetect;
|
use Text_LanguageDetect;
|
||||||
|
|
||||||
class Item extends BaseObject
|
class Item extends BaseObject
|
||||||
|
@ -87,7 +88,7 @@ class Item extends BaseObject
|
||||||
'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', 'network',
|
'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', 'network',
|
||||||
'title', 'content-warning', 'body', 'location', 'coord', 'app',
|
'title', 'content-warning', 'body', 'location', 'coord', 'app',
|
||||||
'rendered-hash', 'rendered-html', 'object-type', 'object', 'target-type', 'target',
|
'rendered-hash', 'rendered-html', 'object-type', 'object', 'target-type', 'target',
|
||||||
'author-id', 'author-link', 'author-name', 'author-avatar',
|
'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network',
|
||||||
'owner-id', 'owner-link', 'owner-name', 'owner-avatar'];
|
'owner-id', 'owner-link', 'owner-name', 'owner-avatar'];
|
||||||
|
|
||||||
// Never reorder or remove entries from this list. Just add new ones at the end, if needed.
|
// Never reorder or remove entries from this list. Just add new ones at the end, if needed.
|
||||||
|
@ -925,7 +926,7 @@ class Item extends BaseObject
|
||||||
// We only need to notfiy others when it is an original entry from us.
|
// We only need to notfiy others when it is an original entry from us.
|
||||||
// Only call the notifier when the item has some content relevant change.
|
// Only call the notifier when the item has some content relevant change.
|
||||||
if ($item['origin'] && in_array('edited', array_keys($fields))) {
|
if ($item['origin'] && in_array('edited', array_keys($fields))) {
|
||||||
Worker::add(PRIORITY_HIGH, "Notifier", 'edit_post', $item['id']);
|
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::POST, $item['id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,9 +1080,11 @@ class Item extends BaseObject
|
||||||
}
|
}
|
||||||
// When the permission set will be used in photo and events as well,
|
// When the permission set will be used in photo and events as well,
|
||||||
// this query here needs to be extended.
|
// this query here needs to be extended.
|
||||||
if (!empty($item['psid']) && !self::exists(['psid' => $item['psid'], 'deleted' => false])) {
|
// @todo Currently deactivated. We need the permission set in the deletion process.
|
||||||
DBA::delete('permissionset', ['id' => $item['psid']], ['cascade' => false]);
|
// This is a reminder to add the removal somewhere else.
|
||||||
}
|
//if (!empty($item['psid']) && !self::exists(['psid' => $item['psid'], 'deleted' => false])) {
|
||||||
|
// DBA::delete('permissionset', ['id' => $item['psid']], ['cascade' => false]);
|
||||||
|
//}
|
||||||
|
|
||||||
// If it's the parent of a comment thread, kill all the kids
|
// If it's the parent of a comment thread, kill all the kids
|
||||||
if ($item['id'] == $item['parent']) {
|
if ($item['id'] == $item['parent']) {
|
||||||
|
@ -1095,7 +1098,7 @@ class Item extends BaseObject
|
||||||
self::delete(['uri' => $item['uri'], 'deleted' => false], $priority);
|
self::delete(['uri' => $item['uri'], 'deleted' => false], $priority);
|
||||||
|
|
||||||
// send the notification upstream/downstream
|
// send the notification upstream/downstream
|
||||||
Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", intval($item['id']));
|
Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", Delivery::DELETION, intval($item['id']));
|
||||||
} elseif ($item['uid'] != 0) {
|
} elseif ($item['uid'] != 0) {
|
||||||
|
|
||||||
// When we delete just our local user copy of an item, we have to set a marker to hide it
|
// When we delete just our local user copy of an item, we have to set a marker to hide it
|
||||||
|
@ -1452,6 +1455,11 @@ class Item extends BaseObject
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($uid) && Contact::isBlockedByUser($item['author-id'], $uid)) {
|
||||||
|
Logger::notice('Author is blocked by user', ['author-link' => $item['author-link'], 'uid' => $uid, 'item-uri' => $item['uri']]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
$default = ['url' => $item['owner-link'], 'name' => $item['owner-name'],
|
$default = ['url' => $item['owner-link'], 'name' => $item['owner-name'],
|
||||||
'photo' => $item['owner-avatar'], 'network' => $item['network']];
|
'photo' => $item['owner-avatar'], 'network' => $item['network']];
|
||||||
|
|
||||||
|
@ -1467,6 +1475,26 @@ class Item extends BaseObject
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($uid) && Contact::isBlockedByUser($item['owner-id'], $uid)) {
|
||||||
|
Logger::notice('Owner is blocked by user', ['owner-link' => $item['owner-link'], 'uid' => $uid, 'item-uri' => $item['uri']]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The causer is set during a thread completion, for example because of a reshare. It countains the responsible actor.
|
||||||
|
if (!empty($uid) && !empty($item['causer-id']) && Contact::isBlockedByUser($item['causer-id'], $uid)) {
|
||||||
|
Logger::notice('Causer is blocked by user', ['causer-link' => $item['causer-link'], 'uid' => $uid, 'item-uri' => $item['uri']]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($uid) && !empty($item['causer-id']) && ($item['parent-uri'] == $item['uri']) && Contact::isIgnoredByUser($item['causer-id'], $uid)) {
|
||||||
|
Logger::notice('Causer is ignored by user', ['causer-link' => $item['causer-link'], 'uid' => $uid, 'item-uri' => $item['uri']]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't store the causer, we only have it here for the checks above
|
||||||
|
unset($item['causer-id']);
|
||||||
|
unset($item['causer-link']);
|
||||||
|
|
||||||
if ($item['network'] == Protocol::PHANTOM) {
|
if ($item['network'] == Protocol::PHANTOM) {
|
||||||
$item['network'] = Protocol::DFRN;
|
$item['network'] = Protocol::DFRN;
|
||||||
Logger::notice('Missing network, setting to {network}.', [
|
Logger::notice('Missing network, setting to {network}.', [
|
||||||
|
@ -1508,7 +1536,7 @@ class Item extends BaseObject
|
||||||
|
|
||||||
$item['thr-parent'] = $item['parent-uri'];
|
$item['thr-parent'] = $item['parent-uri'];
|
||||||
|
|
||||||
$notify_type = '';
|
$notify_type = Delivery::POST;
|
||||||
$allow_cid = '';
|
$allow_cid = '';
|
||||||
$allow_gid = '';
|
$allow_gid = '';
|
||||||
$deny_cid = '';
|
$deny_cid = '';
|
||||||
|
@ -1521,7 +1549,6 @@ class Item extends BaseObject
|
||||||
$allow_gid = $item['allow_gid'];
|
$allow_gid = $item['allow_gid'];
|
||||||
$deny_cid = $item['deny_cid'];
|
$deny_cid = $item['deny_cid'];
|
||||||
$deny_gid = $item['deny_gid'];
|
$deny_gid = $item['deny_gid'];
|
||||||
$notify_type = 'wall-new';
|
|
||||||
} else {
|
} else {
|
||||||
// find the parent and snarf the item id and ACLs
|
// find the parent and snarf the item id and ACLs
|
||||||
// and anything else we need to inherit
|
// and anything else we need to inherit
|
||||||
|
@ -1558,8 +1585,7 @@ class Item extends BaseObject
|
||||||
$allow_gid = $parent['allow_gid'];
|
$allow_gid = $parent['allow_gid'];
|
||||||
$deny_cid = $parent['deny_cid'];
|
$deny_cid = $parent['deny_cid'];
|
||||||
$deny_gid = $parent['deny_gid'];
|
$deny_gid = $parent['deny_gid'];
|
||||||
$item['wall'] = $parent['wall'];
|
$item['wall'] = $parent['wall'];
|
||||||
$notify_type = 'comment-new';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the parent is private, force privacy for the entire conversation
|
* If the parent is private, force privacy for the entire conversation
|
||||||
|
@ -1603,6 +1629,10 @@ class Item extends BaseObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stristr($item['verb'], ACTIVITY_POKE)) {
|
||||||
|
$notify_type = Delivery::POKE;
|
||||||
|
}
|
||||||
|
|
||||||
$item['parent-uri-id'] = ItemURI::getIdByURI($item['parent-uri']);
|
$item['parent-uri-id'] = ItemURI::getIdByURI($item['parent-uri']);
|
||||||
$item['thr-parent-id'] = ItemURI::getIdByURI($item['thr-parent']);
|
$item['thr-parent-id'] = ItemURI::getIdByURI($item['thr-parent']);
|
||||||
|
|
||||||
|
@ -1721,6 +1751,7 @@ class Item extends BaseObject
|
||||||
unset($item['author-link']);
|
unset($item['author-link']);
|
||||||
unset($item['author-name']);
|
unset($item['author-name']);
|
||||||
unset($item['author-avatar']);
|
unset($item['author-avatar']);
|
||||||
|
unset($item['author-network']);
|
||||||
|
|
||||||
unset($item['owner-link']);
|
unset($item['owner-link']);
|
||||||
unset($item['owner-name']);
|
unset($item['owner-name']);
|
||||||
|
@ -1876,18 +1907,8 @@ class Item extends BaseObject
|
||||||
|
|
||||||
check_user_notification($current_post);
|
check_user_notification($current_post);
|
||||||
|
|
||||||
if ($notify) {
|
if ($notify || ($item['visible'] && ((!empty($parent) && $parent['origin']) || $item['origin']))) {
|
||||||
Worker::add(['priority' => $priority, 'dont_fork' => true], 'Notifier', $notify_type, $current_post);
|
Worker::add(['priority' => $priority, 'dont_fork' => true], 'Notifier', $notify_type, $current_post);
|
||||||
} elseif ($item['visible'] && ((!empty($parent) && $parent['origin']) || $item['origin'])) {
|
|
||||||
if ($item['gravity'] == GRAVITY_ACTIVITY) {
|
|
||||||
$cmd = $item['origin'] ? 'activity-new' : 'activity-import';
|
|
||||||
} elseif ($item['gravity'] == GRAVITY_COMMENT) {
|
|
||||||
$cmd = $item['origin'] ? 'comment-new' : 'comment-import';
|
|
||||||
} else {
|
|
||||||
$cmd = 'wall-new';
|
|
||||||
}
|
|
||||||
|
|
||||||
Worker::add(['priority' => $priority, 'dont_fork' => true], 'Notifier', $cmd, $current_post);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $current_post;
|
return $current_post;
|
||||||
|
@ -2603,7 +2624,7 @@ class Item extends BaseObject
|
||||||
|
|
||||||
self::updateThread($item_id);
|
self::updateThread($item_id);
|
||||||
|
|
||||||
Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], 'Notifier', 'tgroup', $item_id);
|
Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], 'Notifier', Delivery::POST, $item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isRemoteSelf($contact, &$datarray)
|
public static function isRemoteSelf($contact, &$datarray)
|
||||||
|
@ -2653,7 +2674,6 @@ class Item extends BaseObject
|
||||||
$datarray['author-link'] = $datarray['owner-link'];
|
$datarray['author-link'] = $datarray['owner-link'];
|
||||||
$datarray['author-avatar'] = $datarray['owner-avatar'];
|
$datarray['author-avatar'] = $datarray['owner-avatar'];
|
||||||
|
|
||||||
unset($datarray['created']);
|
|
||||||
unset($datarray['edited']);
|
unset($datarray['edited']);
|
||||||
|
|
||||||
unset($datarray['network']);
|
unset($datarray['network']);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Friendica\Model\Item;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to handle private messages
|
* Class to handle private messages
|
||||||
|
@ -45,6 +46,8 @@ class Mail
|
||||||
$msg['guid'] = Item::guidFromUri($msg['uri'], $host);
|
$msg['guid'] = Item::guidFromUri($msg['uri'], $host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$msg['created'] = (!empty($msg['created']) ? DateTimeFormat::utc($msg['created']) : DateTimeFormat::utcNow());
|
||||||
|
|
||||||
DBA::lock('mail');
|
DBA::lock('mail');
|
||||||
|
|
||||||
if (DBA::exists('mail', ['uri' => $msg['uri'], 'uid' => $msg['uid']])) {
|
if (DBA::exists('mail', ['uri' => $msg['uri'], 'uid' => $msg['uid']])) {
|
||||||
|
@ -72,7 +75,7 @@ class Mail
|
||||||
'to_email' => $user['email'],
|
'to_email' => $user['email'],
|
||||||
'uid' => $user['uid'],
|
'uid' => $user['uid'],
|
||||||
'item' => $msg,
|
'item' => $msg,
|
||||||
'parent' => $msg['parent-uri'],
|
'parent' => 0,
|
||||||
'source_name' => $msg['from-name'],
|
'source_name' => $msg['from-name'],
|
||||||
'source_link' => $msg['from-url'],
|
'source_link' => $msg['from-url'],
|
||||||
'source_photo' => $msg['from-photo'],
|
'source_photo' => $msg['from-photo'],
|
||||||
|
@ -218,7 +221,7 @@ class Mail
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($post_id) {
|
if ($post_id) {
|
||||||
Worker::add(PRIORITY_HIGH, "Notifier", "mail", $post_id);
|
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::MAIL, $post_id);
|
||||||
return intval($post_id);
|
return intval($post_id);
|
||||||
} else {
|
} else {
|
||||||
return -3;
|
return -3;
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\Database\DBStructure;
|
use Friendica\Database\DBStructure;
|
||||||
use Friendica\Model\Storage\IStorage;
|
use Friendica\Model\Storage\IStorage;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
|
use Friendica\Protocol\DFRN;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Security;
|
use Friendica\Util\Security;
|
||||||
|
@ -133,8 +134,16 @@ class Photo extends BaseObject
|
||||||
if ($r === false) {
|
if ($r === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$uid = $r["uid"];
|
||||||
|
|
||||||
$sql_acl = Security::getPermissionsSQLByUserId($r["uid"]);
|
// This is the first place, when retrieving just a photo, that we know who owns the photo.
|
||||||
|
// Make sure that the requester's session is appropriately authenticated to that user
|
||||||
|
// otherwise permissions checks done by getPermissionsSQLByUserId() won't work correctly
|
||||||
|
$r = DBA::selectFirst("user", ["nickname"], ["uid" => $uid], []);
|
||||||
|
// this will either just return (if auth all ok) or will redirect and exit (starting over)
|
||||||
|
DFRN::autoRedir(self::getApp(), $r["nickname"]);
|
||||||
|
|
||||||
|
$sql_acl = Security::getPermissionsSQLByUserId($uid);
|
||||||
|
|
||||||
$conditions = [
|
$conditions = [
|
||||||
"`resource-id` = ? AND `scale` <= ? " . $sql_acl,
|
"`resource-id` = ? AND `scale` <= ? " . $sql_acl,
|
||||||
|
@ -413,13 +422,22 @@ class Photo extends BaseObject
|
||||||
$photo_failure = false;
|
$photo_failure = false;
|
||||||
|
|
||||||
$filename = basename($image_url);
|
$filename = basename($image_url);
|
||||||
$img_str = Network::fetchUrl($image_url, true);
|
if (!empty($image_url)) {
|
||||||
|
$ret = Network::curl($image_url, true);
|
||||||
|
$img_str = $ret->getBody();
|
||||||
|
$type = $ret->getContentType();
|
||||||
|
} else {
|
||||||
|
$img_str = '';
|
||||||
|
}
|
||||||
|
|
||||||
if ($quit_on_error && ($img_str == "")) {
|
if ($quit_on_error && ($img_str == "")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = Image::guessType($image_url, true);
|
if (empty($type)) {
|
||||||
|
$type = Image::guessType($image_url, true);
|
||||||
|
}
|
||||||
|
|
||||||
$Image = new Image($img_str, $type);
|
$Image = new Image($img_str, $type);
|
||||||
if ($Image->isValid()) {
|
if ($Image->isValid()) {
|
||||||
$Image->scaleToSquare(300);
|
$Image->scaleToSquare(300);
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Friendica\Core\Logger;
|
||||||
use Friendica\Core\PConfig;
|
use Friendica\Core\PConfig;
|
||||||
use Friendica\Core\Protocol;
|
use Friendica\Core\Protocol;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
|
use Friendica\Core\Session;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
@ -116,8 +117,13 @@ class Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($profiledata) > 0) {
|
if (count($profiledata) > 0) {
|
||||||
|
// Ensure to have a "nickname" field
|
||||||
|
if (empty($profiledata['nickname']) && !empty($profiledata['nick'])) {
|
||||||
|
$profiledata['nickname'] = $profiledata['nick'];
|
||||||
|
}
|
||||||
|
|
||||||
// Add profile data to sidebar
|
// Add profile data to sidebar
|
||||||
$a->page['aside'] .= self::sidebar($profiledata, true, $show_connect);
|
$a->page['aside'] .= self::sidebar($a, $profiledata, true, $show_connect);
|
||||||
|
|
||||||
if (!DBA::isResult($user)) {
|
if (!DBA::isResult($user)) {
|
||||||
return;
|
return;
|
||||||
|
@ -188,7 +194,7 @@ class Profile
|
||||||
* But: When this profile was on the same server, then we could display the contacts
|
* But: When this profile was on the same server, then we could display the contacts
|
||||||
*/
|
*/
|
||||||
if (!$profiledata) {
|
if (!$profiledata) {
|
||||||
$a->page['aside'] .= self::sidebar($a->profile, $block, $show_connect);
|
$a->page['aside'] .= self::sidebar($a, $a->profile, $block, $show_connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -280,10 +286,8 @@ class Profile
|
||||||
* @hooks 'profile_sidebar'
|
* @hooks 'profile_sidebar'
|
||||||
* array $arr
|
* array $arr
|
||||||
*/
|
*/
|
||||||
private static function sidebar($profile, $block = 0, $show_connect = true)
|
private static function sidebar(App $a, $profile, $block = 0, $show_connect = true)
|
||||||
{
|
{
|
||||||
$a = \get_app();
|
|
||||||
|
|
||||||
$o = '';
|
$o = '';
|
||||||
$location = false;
|
$location = false;
|
||||||
|
|
||||||
|
@ -304,127 +308,102 @@ class Profile
|
||||||
|
|
||||||
Hook::callAll('profile_sidebar_enter', $profile);
|
Hook::callAll('profile_sidebar_enter', $profile);
|
||||||
|
|
||||||
|
if (isset($profile['url'])) {
|
||||||
|
$profile_url = $profile['url'];
|
||||||
|
} else {
|
||||||
|
$profile_url = $a->getBaseURL() . '/profile/' . $profile['nickname'];
|
||||||
|
}
|
||||||
|
|
||||||
// don't show connect link to yourself
|
$follow_link = null;
|
||||||
$connect = $profile['uid'] != local_user() ? L10n::t('Connect') : false;
|
$unfollow_link = null;
|
||||||
|
$subscribe_feed_link = null;
|
||||||
|
$wallmessage_link = null;
|
||||||
|
|
||||||
// don't show connect link to authenticated visitors either
|
|
||||||
if (remote_user() && !empty($_SESSION['remote'])) {
|
|
||||||
foreach ($_SESSION['remote'] as $visitor) {
|
$visitor_contact = [];
|
||||||
if ($visitor['uid'] == $profile['uid']) {
|
if (!empty($profile['uid']) && self::getMyURL()) {
|
||||||
$connect = false;
|
$visitor_contact = Contact::selectFirst(['rel'], ['uid' => $profile['uid'], 'nurl' => Strings::normaliseLink(self::getMyURL())]);
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
$profile_contact = [];
|
||||||
|
if (!empty($profile['cid']) && self::getMyURL()) {
|
||||||
|
$profile_contact = Contact::selectFirst(['rel'], ['id' => $profile['cid']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile_is_dfrn = $profile['network'] == Protocol::DFRN;
|
||||||
|
$profile_is_native = in_array($profile['network'], Protocol::NATIVE_SUPPORT);
|
||||||
|
$local_user_is_self = local_user() && local_user() == ($profile['profile_uid'] ?? 0);
|
||||||
|
$visitor_is_authenticated = (bool)self::getMyURL();
|
||||||
|
$visitor_is_following =
|
||||||
|
in_array($visitor_contact['rel'] ?? 0, [Contact::FOLLOWER, Contact::FRIEND])
|
||||||
|
|| in_array($profile_contact['rel'] ?? 0, [Contact::SHARING, Contact::FRIEND]);
|
||||||
|
$visitor_is_followed =
|
||||||
|
in_array($visitor_contact['rel'] ?? 0, [Contact::SHARING, Contact::FRIEND])
|
||||||
|
|| in_array($profile_contact['rel'] ?? 0, [Contact::FOLLOWER, Contact::FRIEND]);
|
||||||
|
$visitor_base_path = self::getMyURL() ? preg_replace('=/profile/(.*)=ism', '', self::getMyURL()) : '';
|
||||||
|
|
||||||
|
if (!$local_user_is_self && $show_connect) {
|
||||||
|
if (!$visitor_is_authenticated) {
|
||||||
|
$follow_link = 'dfrn_request/' . $profile['nickname'];
|
||||||
|
} elseif ($profile_is_native) {
|
||||||
|
if ($visitor_is_following) {
|
||||||
|
$unfollow_link = $visitor_base_path . '/unfollow?url=' . urlencode($profile_url);
|
||||||
|
} else {
|
||||||
|
$follow_link = $visitor_base_path .'/follow?url=' . urlencode($profile_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!$show_connect) {
|
if ($profile_is_dfrn) {
|
||||||
$connect = false;
|
$subscribe_feed_link = 'dfrn_poll/' . $profile['nickname'];
|
||||||
}
|
|
||||||
|
|
||||||
$profile_url = '';
|
|
||||||
|
|
||||||
// Is the local user already connected to that user?
|
|
||||||
if ($connect && local_user()) {
|
|
||||||
if (isset($profile['url'])) {
|
|
||||||
$profile_url = Strings::normaliseLink($profile['url']);
|
|
||||||
} else {
|
|
||||||
$profile_url = Strings::normaliseLink(System::baseUrl() . '/profile/' . $profile['nickname']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DBA::exists('contact', ['pending' => false, 'uid' => local_user(), 'nurl' => $profile_url])) {
|
if (Contact::canReceivePrivateMessages($profile)) {
|
||||||
$connect = false;
|
if ($visitor_is_followed || $visitor_is_following) {
|
||||||
}
|
$wallmessage_link = $visitor_base_path . '/message/new/' . base64_encode(defaults($profile, 'addr', ''));
|
||||||
}
|
} elseif ($visitor_is_authenticated && !empty($profile['unkmail'])) {
|
||||||
|
$wallmessage_link = 'wallmessage/' . $profile['nickname'];
|
||||||
// Is the remote user already connected to that user?
|
}
|
||||||
if ($connect && Contact::isFollower(remote_user(), $profile['uid'])) {
|
|
||||||
$connect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($connect && ($profile['network'] != Protocol::DFRN) && !isset($profile['remoteconnect'])) {
|
|
||||||
$connect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$remoteconnect = null;
|
|
||||||
if (isset($profile['remoteconnect'])) {
|
|
||||||
$remoteconnect = $profile['remoteconnect'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($connect && ($profile['network'] == Protocol::DFRN) && !isset($remoteconnect)) {
|
|
||||||
$subscribe_feed = L10n::t('Atom feed');
|
|
||||||
} else {
|
|
||||||
$subscribe_feed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wallmessage = false;
|
|
||||||
$wallmessage_link = false;
|
|
||||||
|
|
||||||
// See issue https://github.com/friendica/friendica/issues/3838
|
|
||||||
// Either we remove the message link for remote users or we enable creating messages from remote users
|
|
||||||
if (remote_user() || (self::getMyURL() && !empty($profile['unkmail']) && ($profile['uid'] != local_user()))) {
|
|
||||||
$wallmessage = L10n::t('Message');
|
|
||||||
|
|
||||||
if (remote_user()) {
|
|
||||||
$r = q(
|
|
||||||
"SELECT `url` FROM `contact` WHERE `uid` = %d AND `id` = '%s' AND `rel` = %d",
|
|
||||||
intval($profile['uid']),
|
|
||||||
intval(remote_user()),
|
|
||||||
intval(Contact::FRIEND)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$r = q(
|
|
||||||
"SELECT `url` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `rel` = %d",
|
|
||||||
intval($profile['uid']),
|
|
||||||
DBA::escape(Strings::normaliseLink(self::getMyURL())),
|
|
||||||
intval(Contact::FRIEND)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($r) {
|
|
||||||
$remote_url = $r[0]['url'];
|
|
||||||
$message_path = preg_replace('=(.*)/profile/(.*)=ism', '$1/message/new/', $remote_url);
|
|
||||||
$wallmessage_link = $message_path . base64_encode(defaults($profile, 'addr', ''));
|
|
||||||
} else if (!empty($profile['nickname'])) {
|
|
||||||
$wallmessage_link = 'wallmessage/' . $profile['nickname'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// show edit profile to yourself
|
// show edit profile to yourself
|
||||||
if (!$is_contact && $profile['uid'] == local_user() && Feature::isEnabled(local_user(), 'multi_profiles')) {
|
if (!$is_contact && $local_user_is_self) {
|
||||||
$profile['edit'] = [System::baseUrl() . '/profiles', L10n::t('Profiles'), '', L10n::t('Manage/edit profiles')];
|
if (Feature::isEnabled(local_user(), 'multi_profiles')) {
|
||||||
$r = q(
|
$profile['edit'] = [System::baseUrl() . '/profiles', L10n::t('Profiles'), '', L10n::t('Manage/edit profiles')];
|
||||||
"SELECT * FROM `profile` WHERE `uid` = %d",
|
$r = q(
|
||||||
local_user()
|
"SELECT * FROM `profile` WHERE `uid` = %d",
|
||||||
);
|
local_user()
|
||||||
|
);
|
||||||
|
|
||||||
$profile['menu'] = [
|
$profile['menu'] = [
|
||||||
'chg_photo' => L10n::t('Change profile photo'),
|
'chg_photo' => L10n::t('Change profile photo'),
|
||||||
'cr_new' => L10n::t('Create New Profile'),
|
'cr_new' => L10n::t('Create New Profile'),
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
foreach ($r as $rr) {
|
foreach ($r as $rr) {
|
||||||
$profile['menu']['entries'][] = [
|
$profile['menu']['entries'][] = [
|
||||||
'photo' => $rr['thumb'],
|
'photo' => $rr['thumb'],
|
||||||
'id' => $rr['id'],
|
'id' => $rr['id'],
|
||||||
'alt' => L10n::t('Profile Image'),
|
'alt' => L10n::t('Profile Image'),
|
||||||
'profile_name' => $rr['profile-name'],
|
'profile_name' => $rr['profile-name'],
|
||||||
'isdefault' => $rr['is-default'],
|
'isdefault' => $rr['is-default'],
|
||||||
'visibile_to_everybody' => L10n::t('visible to everybody'),
|
'visibile_to_everybody' => L10n::t('visible to everybody'),
|
||||||
'edit_visibility' => L10n::t('Edit visibility'),
|
'edit_visibility' => L10n::t('Edit visibility'),
|
||||||
];
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$profile['edit'] = [System::baseUrl() . '/profiles/' . $profile['id'], L10n::t('Edit profile'), '', L10n::t('Edit profile')];
|
||||||
|
$profile['menu'] = [
|
||||||
|
'chg_photo' => L10n::t('Change profile photo'),
|
||||||
|
'cr_new' => null,
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$is_contact && $profile['uid'] == local_user() && !Feature::isEnabled(local_user(), 'multi_profiles')) {
|
|
||||||
$profile['edit'] = [System::baseUrl() . '/profiles/' . $profile['id'], L10n::t('Edit profile'), '', L10n::t('Edit profile')];
|
|
||||||
$profile['menu'] = [
|
|
||||||
'chg_photo' => L10n::t('Change profile photo'),
|
|
||||||
'cr_new' => null,
|
|
||||||
'entries' => [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the account type
|
// Fetch the account type
|
||||||
$account_type = Contact::getAccountType($profile);
|
$account_type = Contact::getAccountType($profile);
|
||||||
|
@ -525,10 +504,13 @@ class Profile
|
||||||
$o .= Renderer::replaceMacros($tpl, [
|
$o .= Renderer::replaceMacros($tpl, [
|
||||||
'$profile' => $p,
|
'$profile' => $p,
|
||||||
'$xmpp' => $xmpp,
|
'$xmpp' => $xmpp,
|
||||||
'$connect' => $connect,
|
'$follow' => L10n::t('Follow'),
|
||||||
'$remoteconnect' => $remoteconnect,
|
'$follow_link' => $follow_link,
|
||||||
'$subscribe_feed' => $subscribe_feed,
|
'$unfollow' => L10n::t('Unfollow'),
|
||||||
'$wallmessage' => $wallmessage,
|
'$unfollow_link' => $unfollow_link,
|
||||||
|
'$subscribe_feed' => L10n::t('Atom feed'),
|
||||||
|
'$subscribe_feed_link' => $subscribe_feed_link,
|
||||||
|
'$wallmessage' => L10n::t('Message'),
|
||||||
'$wallmessage_link' => $wallmessage_link,
|
'$wallmessage_link' => $wallmessage_link,
|
||||||
'$account_type' => $account_type,
|
'$account_type' => $account_type,
|
||||||
'$location' => $location,
|
'$location' => $location,
|
||||||
|
@ -877,32 +859,35 @@ class Profile
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTabs($a, $is_owner = false, $nickname = null)
|
/**
|
||||||
|
* @param App $a
|
||||||
|
* @param string $current
|
||||||
|
* @param bool $is_owner
|
||||||
|
* @param string $nickname
|
||||||
|
* @return string
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public static function getTabs(App $a, string $current, bool $is_owner, string $nickname = null)
|
||||||
{
|
{
|
||||||
if (is_null($nickname)) {
|
if (is_null($nickname)) {
|
||||||
$nickname = $a->user['nickname'];
|
$nickname = $a->user['nickname'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$tab = false;
|
$baseProfileUrl = System::baseUrl() . '/profile/' . $nickname;
|
||||||
if (!empty($_GET['tab'])) {
|
|
||||||
$tab = Strings::escapeTags(trim($_GET['tab']));
|
|
||||||
}
|
|
||||||
|
|
||||||
$url = System::baseUrl() . '/profile/' . $nickname;
|
|
||||||
|
|
||||||
$tabs = [
|
$tabs = [
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Status'),
|
'label' => L10n::t('Status'),
|
||||||
'url' => $url,
|
'url' => $baseProfileUrl,
|
||||||
'sel' => !$tab && $a->argv[0] == 'profile' ? 'active' : '',
|
'sel' => !$current ? 'active' : '',
|
||||||
'title' => L10n::t('Status Messages and Posts'),
|
'title' => L10n::t('Status Messages and Posts'),
|
||||||
'id' => 'status-tab',
|
'id' => 'status-tab',
|
||||||
'accesskey' => 'm',
|
'accesskey' => 'm',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Profile'),
|
'label' => L10n::t('Profile'),
|
||||||
'url' => $url . '/?tab=profile',
|
'url' => $baseProfileUrl . '/?tab=profile',
|
||||||
'sel' => $tab == 'profile' ? 'active' : '',
|
'sel' => $current == 'profile' ? 'active' : '',
|
||||||
'title' => L10n::t('Profile Details'),
|
'title' => L10n::t('Profile Details'),
|
||||||
'id' => 'profile-tab',
|
'id' => 'profile-tab',
|
||||||
'accesskey' => 'r',
|
'accesskey' => 'r',
|
||||||
|
@ -910,7 +895,7 @@ class Profile
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Photos'),
|
'label' => L10n::t('Photos'),
|
||||||
'url' => System::baseUrl() . '/photos/' . $nickname,
|
'url' => System::baseUrl() . '/photos/' . $nickname,
|
||||||
'sel' => !$tab && $a->argv[0] == 'photos' ? 'active' : '',
|
'sel' => $current == 'photos' ? 'active' : '',
|
||||||
'title' => L10n::t('Photo Albums'),
|
'title' => L10n::t('Photo Albums'),
|
||||||
'id' => 'photo-tab',
|
'id' => 'photo-tab',
|
||||||
'accesskey' => 'h',
|
'accesskey' => 'h',
|
||||||
|
@ -918,7 +903,7 @@ class Profile
|
||||||
[
|
[
|
||||||
'label' => L10n::t('Videos'),
|
'label' => L10n::t('Videos'),
|
||||||
'url' => System::baseUrl() . '/videos/' . $nickname,
|
'url' => System::baseUrl() . '/videos/' . $nickname,
|
||||||
'sel' => !$tab && $a->argv[0] == 'videos' ? 'active' : '',
|
'sel' => $current == 'videos' ? 'active' : '',
|
||||||
'title' => L10n::t('Videos'),
|
'title' => L10n::t('Videos'),
|
||||||
'id' => 'video-tab',
|
'id' => 'video-tab',
|
||||||
'accesskey' => 'v',
|
'accesskey' => 'v',
|
||||||
|
@ -930,7 +915,7 @@ class Profile
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Events'),
|
'label' => L10n::t('Events'),
|
||||||
'url' => System::baseUrl() . '/events',
|
'url' => System::baseUrl() . '/events',
|
||||||
'sel' => !$tab && $a->argv[0] == 'events' ? 'active' : '',
|
'sel' => $current == 'events' ? 'active' : '',
|
||||||
'title' => L10n::t('Events and Calendar'),
|
'title' => L10n::t('Events and Calendar'),
|
||||||
'id' => 'events-tab',
|
'id' => 'events-tab',
|
||||||
'accesskey' => 'e',
|
'accesskey' => 'e',
|
||||||
|
@ -941,7 +926,7 @@ class Profile
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Events'),
|
'label' => L10n::t('Events'),
|
||||||
'url' => System::baseUrl() . '/cal/' . $nickname,
|
'url' => System::baseUrl() . '/cal/' . $nickname,
|
||||||
'sel' => !$tab && $a->argv[0] == 'cal' ? 'active' : '',
|
'sel' => $current == 'cal' ? 'active' : '',
|
||||||
'title' => L10n::t('Events and Calendar'),
|
'title' => L10n::t('Events and Calendar'),
|
||||||
'id' => 'events-tab',
|
'id' => 'events-tab',
|
||||||
'accesskey' => 'e',
|
'accesskey' => 'e',
|
||||||
|
@ -952,7 +937,7 @@ class Profile
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Personal Notes'),
|
'label' => L10n::t('Personal Notes'),
|
||||||
'url' => System::baseUrl() . '/notes',
|
'url' => System::baseUrl() . '/notes',
|
||||||
'sel' => !$tab && $a->argv[0] == 'notes' ? 'active' : '',
|
'sel' => $current == 'notes' ? 'active' : '',
|
||||||
'title' => L10n::t('Only You Can See This'),
|
'title' => L10n::t('Only You Can See This'),
|
||||||
'id' => 'notes-tab',
|
'id' => 'notes-tab',
|
||||||
'accesskey' => 't',
|
'accesskey' => 't',
|
||||||
|
@ -969,18 +954,18 @@ class Profile
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$is_owner && empty($a->profile['hide-friends'])) {
|
if ($is_owner || empty($a->profile['hide-friends'])) {
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'label' => L10n::t('Contacts'),
|
'label' => L10n::t('Contacts'),
|
||||||
'url' => System::baseUrl() . '/viewcontacts/' . $nickname,
|
'url' => $baseProfileUrl . '/contacts',
|
||||||
'sel' => !$tab && $a->argv[0] == 'viewcontacts' ? 'active' : '',
|
'sel' => $current == 'contacts' ? 'active' : '',
|
||||||
'title' => L10n::t('Contacts'),
|
'title' => L10n::t('Contacts'),
|
||||||
'id' => 'viewcontacts-tab',
|
'id' => 'viewcontacts-tab',
|
||||||
'accesskey' => 'k',
|
'accesskey' => 'k',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$arr = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $tab, 'tabs' => $tabs];
|
$arr = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $current, 'tabs' => $tabs];
|
||||||
Hook::callAll('profile_tabs', $arr);
|
Hook::callAll('profile_tabs', $arr);
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
|
$tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
|
||||||
|
@ -995,10 +980,7 @@ class Profile
|
||||||
*/
|
*/
|
||||||
public static function getMyURL()
|
public static function getMyURL()
|
||||||
{
|
{
|
||||||
if (!empty($_SESSION['my_url'])) {
|
return Session::get('my_url');
|
||||||
return $_SESSION['my_url'];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,11 +16,13 @@ use Friendica\Core\Protocol;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Util\Crypto;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
use LightOpenID;
|
use LightOpenID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,10 +150,11 @@ class User
|
||||||
* @brief Get owner data by user id
|
* @brief Get owner data by user id
|
||||||
*
|
*
|
||||||
* @param int $uid
|
* @param int $uid
|
||||||
|
* @param boolean $check_valid Test if data is invalid and correct it
|
||||||
* @return boolean|array
|
* @return boolean|array
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static function getOwnerDataById($uid) {
|
public static function getOwnerDataById($uid, $check_valid = true) {
|
||||||
$r = DBA::fetchFirst("SELECT
|
$r = DBA::fetchFirst("SELECT
|
||||||
`contact`.*,
|
`contact`.*,
|
||||||
`user`.`prvkey` AS `uprvkey`,
|
`user`.`prvkey` AS `uprvkey`,
|
||||||
|
@ -179,12 +182,34 @@ class User
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the returned data is valid, otherwise fix it. See issue #6122
|
if (!$check_valid) {
|
||||||
$url = System::baseUrl() . '/profile/' . $r['nickname'];
|
return $r;
|
||||||
$addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
|
}
|
||||||
|
|
||||||
if (($addr != $r['addr']) || ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url']))) {
|
// Check if the returned data is valid, otherwise fix it. See issue #6122
|
||||||
|
|
||||||
|
// Check for correct url and normalised nurl
|
||||||
|
$url = System::baseUrl() . '/profile/' . $r['nickname'];
|
||||||
|
$repair = ($r['url'] != $url) || ($r['nurl'] != Strings::normaliseLink($r['url']));
|
||||||
|
|
||||||
|
if (!$repair) {
|
||||||
|
// Check if "addr" is present and correct
|
||||||
|
$addr = $r['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
|
||||||
|
$repair = ($addr != $r['addr']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$repair) {
|
||||||
|
// Check if the avatar field is filled and the photo directs to the correct path
|
||||||
|
$avatar = Photo::selectFirst(['resource-id'], ['uid' => $uid, 'profile' => true]);
|
||||||
|
if (DBA::isResult($avatar)) {
|
||||||
|
$repair = empty($r['avatar']) || !strpos($r['photo'], $avatar['resource-id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($repair) {
|
||||||
Contact::updateSelfFromUserID($uid);
|
Contact::updateSelfFromUserID($uid);
|
||||||
|
// Return the corrected data and avoid a loop
|
||||||
|
$r = self::getOwnerDataById($uid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $r;
|
return $r;
|
||||||
|
@ -912,7 +937,7 @@ class User
|
||||||
|
|
||||||
// The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php)
|
// The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php)
|
||||||
DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc('now + 7 day')], ['uid' => $uid]);
|
DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc('now + 7 day')], ['uid' => $uid]);
|
||||||
Worker::add(PRIORITY_HIGH, 'Notifier', 'removeme', $uid);
|
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::REMOVAL, $uid);
|
||||||
|
|
||||||
// Send an update to the directory
|
// Send an update to the directory
|
||||||
$self = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]);
|
$self = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]);
|
||||||
|
|
|
@ -87,7 +87,9 @@ class Federation extends BaseAdminModule
|
||||||
$part = array_pop($parts);
|
$part = array_pop($parts);
|
||||||
} while (!empty($parts) && ((strlen($part) >= 40) || (strlen($part) <= 3)));
|
} while (!empty($parts) && ((strlen($part) >= 40) || (strlen($part) <= 3)));
|
||||||
// only take the x.x.x part of the version, not the "release" after the dash
|
// only take the x.x.x part of the version, not the "release" after the dash
|
||||||
$part = array_shift(explode('-', $part));
|
if (!empty($part) && strpos($part, '-')) {
|
||||||
|
$part = explode('-', $part)[0];
|
||||||
|
}
|
||||||
if (!empty($part)) {
|
if (!empty($part)) {
|
||||||
if (empty($compacted[$part])) {
|
if (empty($compacted[$part])) {
|
||||||
$compacted[$part] = $versionCounts[$key]['total'];
|
$compacted[$part] = $versionCounts[$key]['total'];
|
||||||
|
|
|
@ -22,6 +22,12 @@ class Settings extends BaseAdminModule
|
||||||
$debugging = !empty($_POST['debugging']);
|
$debugging = !empty($_POST['debugging']);
|
||||||
$loglevel = defaults($_POST, 'loglevel', LogLevel::ERROR);
|
$loglevel = defaults($_POST, 'loglevel', LogLevel::ERROR);
|
||||||
|
|
||||||
|
if (is_file($logfile) &&
|
||||||
|
!is_writeable($logfile)) {
|
||||||
|
notice(L10n::t('The logfile \'%s\' is not writable. No logging possible', $logfile));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Config::set('system', 'logfile', $logfile);
|
Config::set('system', 'logfile', $logfile);
|
||||||
Config::set('system', 'debugging', $debugging);
|
Config::set('system', 'debugging', $debugging);
|
||||||
Config::set('system', 'loglevel', $loglevel);
|
Config::set('system', 'loglevel', $loglevel);
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Friendica\Protocol\PortableContact;
|
||||||
use Friendica\Util\BasePath;
|
use Friendica\Util\BasePath;
|
||||||
use Friendica\Util\BaseURL;
|
use Friendica\Util\BaseURL;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
require_once __DIR__ . '/../../../boot.php';
|
require_once __DIR__ . '/../../../boot.php';
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ class Site extends BaseAdminModule
|
||||||
// send relocate
|
// send relocate
|
||||||
$usersStmt = DBA::select('user', ['uid'], ['account_removed' => false, 'account_expired' => false]);
|
$usersStmt = DBA::select('user', ['uid'], ['account_removed' => false, 'account_expired' => false]);
|
||||||
while ($user = DBA::fetch($usersStmt)) {
|
while ($user = DBA::fetch($usersStmt)) {
|
||||||
Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $user['uid']);
|
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $user['uid']);
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Relocation started. Could take a while to complete.");
|
info("Relocation started. Could take a while to complete.");
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Summary extends BaseAdminModule
|
||||||
|
|
||||||
// are there MyISAM tables in the DB? If so, trigger a warning message
|
// are there MyISAM tables in the DB? If so, trigger a warning message
|
||||||
$warningtext = [];
|
$warningtext = [];
|
||||||
if (DBA::count('`information_schema`.`tables`', ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) {
|
if (DBA::count(['information_schema' => 'tables'], ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) {
|
||||||
$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');
|
$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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,23 @@ class Summary extends BaseAdminModule
|
||||||
$well_known, $well_known, $a->getBaseURL() . '/help/Install');
|
$well_known, $well_known, $a->getBaseURL() . '/help/Install');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check logfile permission
|
||||||
|
if (Config::get('system', 'debugging')) {
|
||||||
|
$stream = Config::get('system', 'logfile');
|
||||||
|
|
||||||
|
if (is_file($stream) &&
|
||||||
|
!is_writeable($stream)) {
|
||||||
|
$warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream = Config::get('system', 'dlogfile');
|
||||||
|
|
||||||
|
if (is_file($stream) &&
|
||||||
|
!is_writeable($stream)) {
|
||||||
|
$warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check legacy basepath settings
|
// check legacy basepath settings
|
||||||
$configLoader = new ConfigFileLoader($a->getBasePath(), $a->getMode());
|
$configLoader = new ConfigFileLoader($a->getBasePath(), $a->getMode());
|
||||||
$configCache = new Config\Cache\ConfigCache();
|
$configCache = new Config\Cache\ConfigCache();
|
||||||
|
@ -129,8 +146,6 @@ class Summary extends BaseAdminModule
|
||||||
|
|
||||||
$pending = Register::getPendingCount();
|
$pending = Register::getPendingCount();
|
||||||
|
|
||||||
$queue = DBA::count('queue', []);
|
|
||||||
|
|
||||||
$deferred = DBA::count('workerqueue', ['`executed` <= ? AND NOT `done` AND `next_try` > ?',
|
$deferred = DBA::count('workerqueue', ['`executed` <= ? AND NOT `done` AND `next_try` > ?',
|
||||||
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
|
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
|
||||||
|
|
||||||
|
@ -138,7 +153,7 @@ class Summary extends BaseAdminModule
|
||||||
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
|
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
|
||||||
|
|
||||||
// We can do better, but this is a quick queue status
|
// We can do better, but this is a quick queue status
|
||||||
$queues = ['label' => L10n::t('Message queues'), 'queue' => $queue, 'deferred' => $deferred, 'workerq' => $workerqueue];
|
$queues = ['label' => L10n::t('Message queues'), 'deferred' => $deferred, 'workerq' => $workerqueue];
|
||||||
|
|
||||||
$variables = DBA::toArray(DBA::p('SHOW variables LIKE "max_allowed_packet"'));
|
$variables = DBA::toArray(DBA::p('SHOW variables LIKE "max_allowed_packet"'));
|
||||||
$max_allowed_packet = $variables ? $variables[0]['Value'] : 0;
|
$max_allowed_packet = $variables ? $variables[0]['Value'] : 0;
|
||||||
|
|
|
@ -6,7 +6,10 @@ use Friendica\BaseModule;
|
||||||
use Friendica\Core\Addon;
|
use Friendica\Core\Addon;
|
||||||
use Friendica\Core\L10n;
|
use Friendica\Core\L10n;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\Session;
|
||||||
|
use Friendica\Network\HTTPException\ForbiddenException;
|
||||||
|
|
||||||
|
require_once 'boot.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This abstract module is meant to be extended by all modules that are reserved to administrator users.
|
* This abstract module is meant to be extended by all modules that are reserved to administrator users.
|
||||||
|
@ -35,11 +38,11 @@ abstract class BaseAdminModule extends BaseModule
|
||||||
public static function rawContent()
|
public static function rawContent()
|
||||||
{
|
{
|
||||||
if (!is_site_admin()) {
|
if (!is_site_admin()) {
|
||||||
System::httpExit(403);
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_SESSION['submanage'])) {
|
if (!empty($_SESSION['submanage'])) {
|
||||||
System::httpExit(403);
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
|
@ -47,21 +50,18 @@ abstract class BaseAdminModule extends BaseModule
|
||||||
|
|
||||||
public static function content()
|
public static function content()
|
||||||
{
|
{
|
||||||
|
$a = self::getApp();
|
||||||
|
|
||||||
if (!is_site_admin()) {
|
if (!is_site_admin()) {
|
||||||
return Login::form();
|
notice(L10n::t('Please login to continue.'));
|
||||||
|
Session::set('return_path', $a->query_string);
|
||||||
|
$a->internalRedirect('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_SESSION['submanage'])) {
|
if (!empty($_SESSION['submanage'])) {
|
||||||
return '';
|
throw new ForbiddenException(L10n::t('Submanaged account can\'t access the administation pages. Please log back in as the master account.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = self::getApp();
|
|
||||||
|
|
||||||
// APC deactivated, since there are problems with PHP 5.5
|
|
||||||
//if (function_exists("apc_delete")) {
|
|
||||||
// $toDelete = new APCIterator('user', APC_ITER_VALUE);
|
|
||||||
// apc_delete($toDelete);
|
|
||||||
//}
|
|
||||||
// Header stuff
|
// Header stuff
|
||||||
$a->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('admin/settings_head.tpl'), []);
|
$a->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('admin/settings_head.tpl'), []);
|
||||||
|
|
||||||
|
|
167
src/Module/BaseSearchModule.php
Normal file
167
src/Module/BaseSearchModule.php
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Module;
|
||||||
|
|
||||||
|
use Friendica\BaseModule;
|
||||||
|
use Friendica\Content\ContactSelector;
|
||||||
|
use Friendica\Content\Pager;
|
||||||
|
use Friendica\Core\L10n;
|
||||||
|
use Friendica\Core\Renderer;
|
||||||
|
use Friendica\Core\Search;
|
||||||
|
use Friendica\Model;
|
||||||
|
use Friendica\Network\HTTPException;
|
||||||
|
use Friendica\Object\Search\ContactResult;
|
||||||
|
use Friendica\Object\Search\ResultList;
|
||||||
|
use Friendica\Util\Proxy as ProxyUtils;
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for search modules
|
||||||
|
*/
|
||||||
|
class BaseSearchModule extends BaseModule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Performs a search with an optional prefix
|
||||||
|
*
|
||||||
|
* @param string $prefix A optional prefix (e.g. @ or !) for searching
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
public static function performSearch($prefix = '')
|
||||||
|
{
|
||||||
|
$a = self::getApp();
|
||||||
|
$config = $a->getConfig();
|
||||||
|
|
||||||
|
$type = Search::TYPE_ALL;
|
||||||
|
|
||||||
|
$localSearch = $config->get('system', 'poco_local_search');
|
||||||
|
|
||||||
|
$search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', '')));
|
||||||
|
|
||||||
|
if (!$search) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = '';
|
||||||
|
|
||||||
|
if (strpos($search, '@') === 0) {
|
||||||
|
$search = substr($search, 1);
|
||||||
|
$type = Search::TYPE_PEOPLE;
|
||||||
|
$header = L10n::t('People Search - %s', $search);
|
||||||
|
|
||||||
|
if (strrpos($search, '@') > 0) {
|
||||||
|
$results = Search::getContactsFromProbe($search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($search, '!') === 0) {
|
||||||
|
$search = substr($search, 1);
|
||||||
|
$type = Search::TYPE_FORUM;
|
||||||
|
$header = L10n::t('Forum Search - %s', $search);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pager = new Pager($a->query_string);
|
||||||
|
|
||||||
|
if ($localSearch && empty($results)) {
|
||||||
|
$pager->setItemsPerPage(80);
|
||||||
|
$results = Search::getContactsFromLocalDirectory($search, $type, $pager->getStart(), $pager->getItemsPerPage());
|
||||||
|
} elseif (strlen($config->get('system', 'directory')) && empty($results)) {
|
||||||
|
$results = Search::getContactsFromGlobalDirectory($search, $type, $pager->getPage());
|
||||||
|
$pager->setItemsPerPage($results->getItemsPage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::printResult($results, $pager, $header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a human readable search result
|
||||||
|
*
|
||||||
|
* @param ResultList $results
|
||||||
|
* @param Pager $pager
|
||||||
|
* @param string $header
|
||||||
|
*
|
||||||
|
* @return string The result
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
protected static function printResult(ResultList $results, Pager $pager, $header = '')
|
||||||
|
{
|
||||||
|
if ($results->getTotal() == 0) {
|
||||||
|
info(L10n::t('No matches'));
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = self::getApp();
|
||||||
|
|
||||||
|
$id = 0;
|
||||||
|
$entries = [];
|
||||||
|
foreach ($results->getResults() as $result) {
|
||||||
|
|
||||||
|
// in case the result is a contact result, add a contact-specific entry
|
||||||
|
if ($result instanceof ContactResult) {
|
||||||
|
|
||||||
|
$alt_text = '';
|
||||||
|
$location = '';
|
||||||
|
$about = '';
|
||||||
|
$accountType = '';
|
||||||
|
$photo_menu = [];
|
||||||
|
|
||||||
|
// If We already know this contact then don't show the "connect" button
|
||||||
|
if ($result->getCid() > 0 || $result->getPCid() > 0) {
|
||||||
|
$connLink = "";
|
||||||
|
$connTxt = "";
|
||||||
|
$contact = Model\Contact::getById(
|
||||||
|
($result->getCid() > 0) ? $result->getCid() : $result->getPCid()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($contact)) {
|
||||||
|
$photo_menu = Model\Contact::photoMenu($contact);
|
||||||
|
$details = Contact::getContactTemplateVars($contact);
|
||||||
|
$alt_text = $details['alt_text'];
|
||||||
|
$location = $contact['location'];
|
||||||
|
$about = $contact['about'];
|
||||||
|
$accountType = Model\Contact::getAccountType($contact);
|
||||||
|
} else {
|
||||||
|
$photo_menu = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$connLink = $a->getBaseURL() . '/follow/?url=' . $result->getUrl();
|
||||||
|
$connTxt = L10n::t('Connect');
|
||||||
|
|
||||||
|
$photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())];
|
||||||
|
$photo_menu['follow'] = [L10n::t("Connect/Follow"), $connLink];
|
||||||
|
}
|
||||||
|
|
||||||
|
$photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto());
|
||||||
|
|
||||||
|
$entry = [
|
||||||
|
'alt_text' => $alt_text,
|
||||||
|
'url' => Model\Contact::magicLink($result->getUrl()),
|
||||||
|
'itemurl' => $result->getItem(),
|
||||||
|
'name' => $result->getName(),
|
||||||
|
'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB),
|
||||||
|
'img_hover' => $result->getTags(),
|
||||||
|
'conntxt' => $connTxt,
|
||||||
|
'connlnk' => $connLink,
|
||||||
|
'photo_menu' => $photo_menu,
|
||||||
|
'details' => $location,
|
||||||
|
'tags' => $result->getTags(),
|
||||||
|
'about' => $about,
|
||||||
|
'account_type' => $accountType,
|
||||||
|
'network' => ContactSelector::networkToName($result->getNetwork(), $result->getUrl()),
|
||||||
|
'id' => ++$id,
|
||||||
|
];
|
||||||
|
$entries[] = $entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl');
|
||||||
|
return Renderer::replaceMacros($tpl, [
|
||||||
|
'title' => $header,
|
||||||
|
'$contacts' => $entries,
|
||||||
|
'$paginate' => $pager->renderFull($results->getTotal()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -260,12 +260,13 @@ class Contact extends BaseModule
|
||||||
public static function content($update = 0)
|
public static function content($update = 0)
|
||||||
{
|
{
|
||||||
if (!local_user()) {
|
if (!local_user()) {
|
||||||
return Login::form($_SERVER['REQUET_URI']);
|
return Login::form($_SERVER['REQUEST_URI']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = self::getApp();
|
$a = self::getApp();
|
||||||
|
|
||||||
$nets = defaults($_GET, 'nets', '');
|
$nets = defaults($_GET, 'nets', '');
|
||||||
|
$rel = defaults($_GET, 'rel' , '');
|
||||||
|
|
||||||
if (empty($a->page['aside'])) {
|
if (empty($a->page['aside'])) {
|
||||||
$a->page['aside'] = '';
|
$a->page['aside'] = '';
|
||||||
|
@ -308,6 +309,21 @@ class Contact extends BaseModule
|
||||||
$network_link = '';
|
$network_link = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$follow_link = '';
|
||||||
|
$unfollow_link = '';
|
||||||
|
if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
|
||||||
|
if ($contact['uid'] && in_array($contact['rel'], [Model\Contact::SHARING, Model\Contact::FRIEND])) {
|
||||||
|
$unfollow_link = 'unfollow?url=' . urlencode($contact['url']);
|
||||||
|
} elseif(!$contact['pending']) {
|
||||||
|
$follow_link = 'follow?url=' . urlencode($contact['url']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$wallmessage_link = '';
|
||||||
|
if ($contact['uid'] && Model\Contact::canReceivePrivateMessages($contact)) {
|
||||||
|
$wallmessage_link = 'message/new/' . $contact['id'];
|
||||||
|
}
|
||||||
|
|
||||||
$vcard_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/vcard.tpl'), [
|
$vcard_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/vcard.tpl'), [
|
||||||
'$name' => $contact['name'],
|
'$name' => $contact['name'],
|
||||||
'$photo' => $contact['photo'],
|
'$photo' => $contact['photo'],
|
||||||
|
@ -315,12 +331,19 @@ class Contact extends BaseModule
|
||||||
'$addr' => defaults($contact, 'addr', ''),
|
'$addr' => defaults($contact, 'addr', ''),
|
||||||
'$network_link' => $network_link,
|
'$network_link' => $network_link,
|
||||||
'$network' => L10n::t('Network:'),
|
'$network' => L10n::t('Network:'),
|
||||||
'$account_type' => Model\Contact::getAccountType($contact)
|
'$account_type' => Model\Contact::getAccountType($contact),
|
||||||
|
'$follow' => L10n::t('Follow'),
|
||||||
|
'$follow_link' => $follow_link,
|
||||||
|
'$unfollow' => L10n::t('Unfollow'),
|
||||||
|
'$unfollow_link' => $unfollow_link,
|
||||||
|
'$wallmessage' => L10n::t('Message'),
|
||||||
|
'$wallmessage_link' => $wallmessage_link,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$findpeople_widget = '';
|
$findpeople_widget = '';
|
||||||
$follow_widget = '';
|
$follow_widget = '';
|
||||||
$networks_widget = '';
|
$networks_widget = '';
|
||||||
|
$rel_widget = '';
|
||||||
} else {
|
} else {
|
||||||
$vcard_widget = '';
|
$vcard_widget = '';
|
||||||
$findpeople_widget = Widget::findPeople();
|
$findpeople_widget = Widget::findPeople();
|
||||||
|
@ -331,6 +354,7 @@ class Contact extends BaseModule
|
||||||
}
|
}
|
||||||
|
|
||||||
$networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
|
$networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
|
||||||
|
$rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($contact['uid'] != 0) {
|
if ($contact['uid'] != 0) {
|
||||||
|
@ -339,7 +363,7 @@ class Contact extends BaseModule
|
||||||
$groups_widget = null;
|
$groups_widget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$a->page['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget;
|
$a->page['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget . $rel_widget;
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate('contacts-head.tpl');
|
$tpl = Renderer::getMarkupTemplate('contacts-head.tpl');
|
||||||
$a->page['htmlhead'] .= Renderer::replaceMacros($tpl, [
|
$a->page['htmlhead'] .= Renderer::replaceMacros($tpl, [
|
||||||
|
@ -554,19 +578,6 @@ class Contact extends BaseModule
|
||||||
$profile_select = ContactSelector::profileAssign($contact['profile-id'], $contact['network'] !== Protocol::DFRN);
|
$profile_select = ContactSelector::profileAssign($contact['profile-id'], $contact['network'] !== Protocol::DFRN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @todo Only show the following link with DFRN when the remote version supports it
|
|
||||||
$follow = '';
|
|
||||||
$follow_text = '';
|
|
||||||
if ($contact['uid'] && in_array($contact['rel'], [Model\Contact::FRIEND, Model\Contact::SHARING])) {
|
|
||||||
if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
|
|
||||||
$follow = $a->getBaseURL(true) . '/unfollow?url=' . urlencode($contact['url']);
|
|
||||||
$follow_text = L10n::t('Disconnect/Unfollow');
|
|
||||||
}
|
|
||||||
} elseif(!$contact['pending']) {
|
|
||||||
$follow = $a->getBaseURL(true) . '/follow?url=' . urlencode($contact['url']);
|
|
||||||
$follow_text = L10n::t('Connect/Follow');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load contactact related actions like hide, suggest, delete and others
|
// Load contactact related actions like hide, suggest, delete and others
|
||||||
$contact_actions = self::getContactActions($contact);
|
$contact_actions = self::getContactActions($contact);
|
||||||
|
|
||||||
|
@ -607,8 +618,6 @@ class Contact extends BaseModule
|
||||||
'$updpub' => L10n::t('Update public posts'),
|
'$updpub' => L10n::t('Update public posts'),
|
||||||
'$last_update' => $last_update,
|
'$last_update' => $last_update,
|
||||||
'$udnow' => L10n::t('Update now'),
|
'$udnow' => L10n::t('Update now'),
|
||||||
'$follow' => $follow,
|
|
||||||
'$follow_text' => $follow_text,
|
|
||||||
'$profile_select' => $profile_select,
|
'$profile_select' => $profile_select,
|
||||||
'$contact_id' => $contact['id'],
|
'$contact_id' => $contact['id'],
|
||||||
'$block_text' => ($contact['blocked'] ? L10n::t('Unblock') : L10n::t('Block')),
|
'$block_text' => ($contact['blocked'] ? L10n::t('Unblock') : L10n::t('Block')),
|
||||||
|
@ -678,6 +687,7 @@ class Contact extends BaseModule
|
||||||
|
|
||||||
$search = Strings::escapeTags(trim(defaults($_GET, 'search', '')));
|
$search = Strings::escapeTags(trim(defaults($_GET, 'search', '')));
|
||||||
$nets = Strings::escapeTags(trim(defaults($_GET, 'nets' , '')));
|
$nets = Strings::escapeTags(trim(defaults($_GET, 'nets' , '')));
|
||||||
|
$rel = Strings::escapeTags(trim(defaults($_GET, 'rel' , '')));
|
||||||
|
|
||||||
$tabs = [
|
$tabs = [
|
||||||
[
|
[
|
||||||
|
@ -747,6 +757,12 @@ class Contact extends BaseModule
|
||||||
$sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets));
|
$sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch ($rel) {
|
||||||
|
case 'followers': $sql_extra .= " AND `rel` IN (1, 3)"; break;
|
||||||
|
case 'following': $sql_extra .= " AND `rel` IN (2, 3)"; break;
|
||||||
|
case 'mutuals': $sql_extra .= " AND `rel` = 3"; break;
|
||||||
|
}
|
||||||
|
|
||||||
$sql_extra .= " AND NOT `deleted` ";
|
$sql_extra .= " AND NOT `deleted` ";
|
||||||
|
|
||||||
$sql_extra2 = ((($sort_type > 0) && ($sort_type <= Model\Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : '');
|
$sql_extra2 = ((($sort_type > 0) && ($sort_type <= Model\Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : '');
|
||||||
|
@ -777,6 +793,13 @@ class Contact extends BaseModule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch ($rel) {
|
||||||
|
case 'followers': $header = L10n::t('Followers'); break;
|
||||||
|
case 'following': $header = L10n::t('Following'); break;
|
||||||
|
case 'mutuals': $header = L10n::t('Mutual friends'); break;
|
||||||
|
default: $header = L10n::t('Contacts');
|
||||||
|
}
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'blocked': $header .= ' - ' . L10n::t('Blocked'); break;
|
case 'blocked': $header .= ' - ' . L10n::t('Blocked'); break;
|
||||||
case 'hidden': $header .= ' - ' . L10n::t('Hidden'); break;
|
case 'hidden': $header .= ' - ' . L10n::t('Hidden'); break;
|
||||||
|
@ -927,10 +950,6 @@ class Contact extends BaseModule
|
||||||
|
|
||||||
$profiledata = Model\Contact::getDetailsByURL($contact['url']);
|
$profiledata = Model\Contact::getDetailsByURL($contact['url']);
|
||||||
|
|
||||||
if (local_user() && in_array($profiledata['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
|
|
||||||
$profiledata['remoteconnect'] = System::baseUrl() . '/follow?url=' . urlencode($profiledata['url']);
|
|
||||||
}
|
|
||||||
|
|
||||||
Model\Profile::load($a, '', 0, $profiledata, true);
|
Model\Profile::load($a, '', 0, $profiledata, true);
|
||||||
$o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update);
|
$o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ class Fetch extends BaseModule
|
||||||
$item = Item::selectFirst(['author-link'], $condition);
|
$item = Item::selectFirst(['author-link'], $condition);
|
||||||
if (empty($item)) {
|
if (empty($item)) {
|
||||||
$parts = parse_url($item["author-link"]);
|
$parts = parse_url($item["author-link"]);
|
||||||
|
if (empty($parts["scheme"]) || empty($parts["host"])) {
|
||||||
|
throw new HTTPException\InternalServerErrorException();
|
||||||
|
}
|
||||||
$host = $parts["scheme"] . "://" . $parts["host"];
|
$host = $parts["scheme"] . "://" . $parts["host"];
|
||||||
|
|
||||||
if (Strings::normaliseLink($host) != Strings::normaliseLink($app->getBaseURL())) {
|
if (Strings::normaliseLink($host) != Strings::normaliseLink($app->getBaseURL())) {
|
||||||
|
|
|
@ -20,19 +20,6 @@ use Friendica\Util\Strings;
|
||||||
*/
|
*/
|
||||||
class Directory extends BaseModule
|
class Directory extends BaseModule
|
||||||
{
|
{
|
||||||
public static function init()
|
|
||||||
{
|
|
||||||
$app = self::getApp();
|
|
||||||
|
|
||||||
if (local_user()) {
|
|
||||||
$app->page['aside'] .= Widget::findPeople();
|
|
||||||
$app->page['aside'] .= Widget::follow();
|
|
||||||
} else {
|
|
||||||
unset($_SESSION['theme']);
|
|
||||||
unset($_SESSION['mobile-theme']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function content()
|
public static function content()
|
||||||
{
|
{
|
||||||
$app = self::getApp();
|
$app = self::getApp();
|
||||||
|
@ -43,6 +30,14 @@ class Directory extends BaseModule
|
||||||
throw new HTTPException\ForbiddenException(L10n::t('Public access denied.'));
|
throw new HTTPException\ForbiddenException(L10n::t('Public access denied.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (local_user()) {
|
||||||
|
$app->page['aside'] .= Widget::findPeople();
|
||||||
|
$app->page['aside'] .= Widget::follow();
|
||||||
|
} else {
|
||||||
|
unset($_SESSION['theme']);
|
||||||
|
unset($_SESSION['mobile-theme']);
|
||||||
|
}
|
||||||
|
|
||||||
$output = '';
|
$output = '';
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
|
||||||
|
@ -83,7 +78,7 @@ class Directory extends BaseModule
|
||||||
'$globaldir' => L10n::t('Global Directory'),
|
'$globaldir' => L10n::t('Global Directory'),
|
||||||
'$gDirPath' => $gDirPath,
|
'$gDirPath' => $gDirPath,
|
||||||
'$desc' => L10n::t('Find on this site'),
|
'$desc' => L10n::t('Find on this site'),
|
||||||
'$contacts' => $profiles['entries'],
|
'$contacts' => $entries,
|
||||||
'$finding' => L10n::t('Results for:'),
|
'$finding' => L10n::t('Results for:'),
|
||||||
'$findterm' => (strlen($search) ? $search : ""),
|
'$findterm' => (strlen($search) ? $search : ""),
|
||||||
'$title' => L10n::t('Site Directory'),
|
'$title' => L10n::t('Site Directory'),
|
||||||
|
@ -157,7 +152,7 @@ class Directory extends BaseModule
|
||||||
|
|
||||||
$entry = [
|
$entry = [
|
||||||
'id' => $contact['id'],
|
'id' => $contact['id'],
|
||||||
'url' => Contact::magicLInk($profile_link),
|
'url' => Contact::magicLink($profile_link),
|
||||||
'itemurl' => $itemurl,
|
'itemurl' => $itemurl,
|
||||||
'thumb' => ProxyUtils::proxifyUrl($contact[$photo_size], false, ProxyUtils::SIZE_THUMB),
|
'thumb' => ProxyUtils::proxifyUrl($contact[$photo_size], false, ProxyUtils::SIZE_THUMB),
|
||||||
'img_hover' => $contact['name'],
|
'img_hover' => $contact['name'],
|
||||||
|
|
|
@ -46,6 +46,6 @@ class RemoveTag extends BaseModule
|
||||||
info('Item was not deleted');
|
info('Item was not deleted');
|
||||||
}
|
}
|
||||||
|
|
||||||
$app->internalRedirect('/network?f=&file=' . rawurlencode($term));
|
$app->internalRedirect('network?file=' . rawurlencode($term));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,8 @@ class SaveTag extends BaseModule
|
||||||
}
|
}
|
||||||
|
|
||||||
// return filer dialog
|
// return filer dialog
|
||||||
$filetags = PConfig::get(local_user(), 'system', 'filetags');
|
$filetags = PConfig::get(local_user(), 'system', 'filetags', '');
|
||||||
$filetags = Model\FileTag::fileToList($filetags, 'file');
|
$filetags = Model\FileTag::fileToArray($filetags);
|
||||||
$filetags = explode(",", $filetags);
|
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate("filer_dialog.tpl");
|
$tpl = Renderer::getMarkupTemplate("filer_dialog.tpl");
|
||||||
echo Renderer::replaceMacros($tpl, [
|
echo Renderer::replaceMacros($tpl, [
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Friendica\Module\GnuSocial;
|
|
||||||
|
|
||||||
use Friendica\BaseModule;
|
|
||||||
use Friendica\Core\L10n;
|
|
||||||
use Friendica\Database\DBA;
|
|
||||||
use Friendica\Network\HTTPException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GNU Social -> friendica items permanent-url compatibility
|
|
||||||
*/
|
|
||||||
class Notice extends BaseModule
|
|
||||||
{
|
|
||||||
public static function content()
|
|
||||||
{
|
|
||||||
$a = self::getApp();
|
|
||||||
|
|
||||||
// @TODO: Replace with parameter from router
|
|
||||||
$id = ($a->argc > 1) ? $a->argv[1] : 0;
|
|
||||||
|
|
||||||
if (empty($id)) {
|
|
||||||
throw new HTTPException\NotFoundException(L10n::t('Item not found.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = DBA::selectFirst('item', ['guid'], ['id' => $id]);
|
|
||||||
|
|
||||||
if (empty($item )) {
|
|
||||||
throw new HTTPException\NotFoundException(L10n::t('Item not found.'));
|
|
||||||
} else {
|
|
||||||
$a->internalRedirect('display/' . $item['guid']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,8 @@ use Friendica\BaseModule;
|
||||||
use Friendica\Core\Authentication;
|
use Friendica\Core\Authentication;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\L10n;
|
use Friendica\Core\L10n;
|
||||||
|
use Friendica\Core\System;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logout module
|
* Logout module
|
||||||
|
@ -22,9 +24,19 @@ class Logout extends BaseModule
|
||||||
*/
|
*/
|
||||||
public static function init()
|
public static function init()
|
||||||
{
|
{
|
||||||
|
$visitor_home = null;
|
||||||
|
if (remote_user()) {
|
||||||
|
$visitor_home = Profile::getMyURL();
|
||||||
|
}
|
||||||
|
|
||||||
Hook::callAll("logging_out");
|
Hook::callAll("logging_out");
|
||||||
Authentication::deleteSession();
|
Authentication::deleteSession();
|
||||||
info(L10n::t('Logged out.') . EOL);
|
|
||||||
self::getApp()->internalRedirect();
|
if ($visitor_home) {
|
||||||
|
System::externalRedirect($visitor_home);
|
||||||
|
} else {
|
||||||
|
info(L10n::t('Logged out.'));
|
||||||
|
self::getApp()->internalRedirect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Magic extends BaseModule
|
||||||
);
|
);
|
||||||
|
|
||||||
// Try to get an authentication token from the other instance.
|
// Try to get an authentication token from the other instance.
|
||||||
$curlResult = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]);
|
$curlResult = Network::curl($basepath . '/owa', false, ['headers' => $headers]);
|
||||||
|
|
||||||
if ($curlResult->isSuccess()) {
|
if ($curlResult->isSuccess()) {
|
||||||
$j = json_decode($curlResult->getBody(), true);
|
$j = json_decode($curlResult->getBody(), true);
|
||||||
|
|
|
@ -179,12 +179,9 @@ class Profile extends BaseModule
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$update) {
|
if (!$update) {
|
||||||
$tab = false;
|
$tab = Strings::escapeTags(trim(defaults($_GET, 'tab', '')));
|
||||||
if (!empty($_GET['tab'])) {
|
|
||||||
$tab = Strings::escapeTags(trim($_GET['tab']));
|
|
||||||
}
|
|
||||||
|
|
||||||
$o .= ProfileModel::getTabs($a, $is_owner, $a->profile['nickname']);
|
$o .= ProfileModel::getTabs($a, $tab, $is_owner, $a->profile['nickname']);
|
||||||
|
|
||||||
if ($tab === 'profile') {
|
if ($tab === 'profile') {
|
||||||
$o .= ProfileModel::getAdvanced($a);
|
$o .= ProfileModel::getAdvanced($a);
|
||||||
|
@ -197,8 +194,8 @@ class Profile extends BaseModule
|
||||||
$commpage = $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
|
$commpage = $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
|
||||||
$commvisitor = $commpage && $remote_contact;
|
$commvisitor = $commpage && $remote_contact;
|
||||||
|
|
||||||
$a->page['aside'] .= posted_date_widget(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'], true);
|
$a->page['aside'] .= Widget::postedByYear(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'] ?? 0, true);
|
||||||
$a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? XML::escape($category) : ''));
|
$a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], XML::escape($category));
|
||||||
$a->page['aside'] .= Widget::tagCloud();
|
$a->page['aside'] .= Widget::tagCloud();
|
||||||
|
|
||||||
if (Security::canWriteToUserWall($a->profile['profile_uid'])) {
|
if (Security::canWriteToUserWall($a->profile['profile_uid'])) {
|
||||||
|
|
136
src/Module/Profile/Contacts.php
Normal file
136
src/Module/Profile/Contacts.php
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Module\Profile;
|
||||||
|
|
||||||
|
use Friendica\BaseModule;
|
||||||
|
use Friendica\Content\ContactSelector;
|
||||||
|
use Friendica\Content\Nav;
|
||||||
|
use Friendica\Content\Pager;
|
||||||
|
use Friendica\Core\Config;
|
||||||
|
use Friendica\Core\L10n;
|
||||||
|
use Friendica\Core\Protocol;
|
||||||
|
use Friendica\Core\Renderer;
|
||||||
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Model\Contact;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
|
use Friendica\Util\Proxy as ProxyUtils;
|
||||||
|
|
||||||
|
class Contacts extends BaseModule
|
||||||
|
{
|
||||||
|
public static function content()
|
||||||
|
{
|
||||||
|
if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
|
||||||
|
throw new \Friendica\Network\HTTPException\NotFoundException(L10n::t('User not found.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = self::getApp();
|
||||||
|
|
||||||
|
//@TODO: Get value from router parameters
|
||||||
|
$nickname = $a->argv[1];
|
||||||
|
$type = defaults($a->argv, 3, 'all');
|
||||||
|
|
||||||
|
Nav::setSelected('home');
|
||||||
|
|
||||||
|
$user = DBA::selectFirst('user', [], ['nickname' => $nickname, 'blocked' => false]);
|
||||||
|
if (!DBA::isResult($user)) {
|
||||||
|
throw new \Friendica\Network\HTTPException\NotFoundException(L10n::t('User not found.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$a->data['user'] = $user;
|
||||||
|
$a->profile_uid = $user['uid'];
|
||||||
|
|
||||||
|
Profile::load($a, $nickname);
|
||||||
|
|
||||||
|
$is_owner = $a->profile['profile_uid'] == local_user();
|
||||||
|
|
||||||
|
// tabs
|
||||||
|
$o = Profile::getTabs($a, 'contacts', $is_owner, $nickname);
|
||||||
|
|
||||||
|
if (!count($a->profile) || $a->profile['hide-friends']) {
|
||||||
|
notice(L10n::t('Permission denied.') . EOL);
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
$condition = [
|
||||||
|
'uid' => $a->profile['uid'],
|
||||||
|
'blocked' => false,
|
||||||
|
'pending' => false,
|
||||||
|
'hidden' => false,
|
||||||
|
'archive' => false,
|
||||||
|
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::FEED]
|
||||||
|
];
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'followers': $condition['rel'] = [1, 3]; break;
|
||||||
|
case 'following': $condition['rel'] = [2, 3]; break;
|
||||||
|
case 'mutuals': $condition['rel'] = 3; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = DBA::count('contact', $condition);
|
||||||
|
|
||||||
|
$pager = new Pager($a->query_string);
|
||||||
|
|
||||||
|
$params = ['order' => ['name' => false], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
|
||||||
|
|
||||||
|
$contacts_stmt = DBA::select('contact', [], $condition, $params);
|
||||||
|
|
||||||
|
if (!DBA::isResult($contacts_stmt)) {
|
||||||
|
info(L10n::t('No contacts.') . EOL);
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contacts = [];
|
||||||
|
|
||||||
|
while ($contact = DBA::fetch($contacts_stmt)) {
|
||||||
|
if ($contact['self']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact_details = Contact::getDetailsByURL($contact['url'], $a->profile['uid'], $contact);
|
||||||
|
|
||||||
|
$contacts[] = [
|
||||||
|
'id' => $contact['id'],
|
||||||
|
'img_hover' => L10n::t('Visit %s\'s profile [%s]', $contact_details['name'], $contact['url']),
|
||||||
|
'photo_menu' => Contact::photoMenu($contact),
|
||||||
|
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
|
||||||
|
'name' => substr($contact_details['name'], 0, 20),
|
||||||
|
'username' => $contact_details['name'],
|
||||||
|
'details' => $contact_details['location'],
|
||||||
|
'tags' => $contact_details['keywords'],
|
||||||
|
'about' => $contact_details['about'],
|
||||||
|
'account_type' => Contact::getAccountType($contact_details),
|
||||||
|
'url' => Contact::magicLink($contact['url']),
|
||||||
|
'sparkle' => '',
|
||||||
|
'itemurl' => $contact_details['addr'] ? : $contact['url'],
|
||||||
|
'network' => ContactSelector::networkToName($contact['network'], $contact['url']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
DBA::close($contacts_stmt);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'followers': $title = L10n::tt('Follower (%s)', 'Followers (%s)', $total); break;
|
||||||
|
case 'following': $title = L10n::tt('Following (%s)', 'Following (%s)', $total); break;
|
||||||
|
case 'mutuals': $title = L10n::tt('Mutual friend (%s)', 'Mutual friends (%s)', $total); break;
|
||||||
|
|
||||||
|
case 'all': default: $title = L10n::tt('Contact (%s)', 'Contacts (%s)', $total); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tpl = Renderer::getMarkupTemplate('profile/contacts.tpl');
|
||||||
|
$o .= Renderer::replaceMacros($tpl, [
|
||||||
|
'$title' => $title,
|
||||||
|
'$nickname' => $nickname,
|
||||||
|
'$type' => $type,
|
||||||
|
|
||||||
|
'$all_label' => L10n::t('All contacts'),
|
||||||
|
'$followers_label' => L10n::t('Followers'),
|
||||||
|
'$following_label' => L10n::t('Following'),
|
||||||
|
'$mutuals_label' => L10n::t('Mutual friends'),
|
||||||
|
|
||||||
|
'$contacts' => $contacts,
|
||||||
|
'$paginate' => $pager->renderFull($total),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
}
|
32
src/Module/Search/Directory.php
Normal file
32
src/Module/Search/Directory.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Module\Search;
|
||||||
|
|
||||||
|
use Friendica\Content\Widget;
|
||||||
|
use Friendica\Core\L10n;
|
||||||
|
use Friendica\Module\BaseSearchModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directory search module
|
||||||
|
*/
|
||||||
|
class Directory extends BaseSearchModule
|
||||||
|
{
|
||||||
|
public static function content()
|
||||||
|
{
|
||||||
|
if (!local_user()) {
|
||||||
|
notice(L10n::t('Permission denied.'));
|
||||||
|
return Login::form();
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = self::getApp();
|
||||||
|
|
||||||
|
if (empty($a->page['aside'])) {
|
||||||
|
$a->page['aside'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$a->page['aside'] .= Widget::findPeople();
|
||||||
|
$a->page['aside'] .= Widget::follow();
|
||||||
|
|
||||||
|
return self::performSearch();
|
||||||
|
}
|
||||||
|
}
|
69
src/Module/Welcome.php
Normal file
69
src/Module/Welcome.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Module;
|
||||||
|
|
||||||
|
use Friendica\BaseModule;
|
||||||
|
use Friendica\Core\L10n;
|
||||||
|
use Friendica\Core\Renderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the welcome page for new users
|
||||||
|
*/
|
||||||
|
class Welcome extends BaseModule
|
||||||
|
{
|
||||||
|
public static function content()
|
||||||
|
{
|
||||||
|
$config = self::getApp()->getConfig();
|
||||||
|
|
||||||
|
$mail_disabled = ((function_exists('imap_open') &&
|
||||||
|
(!$config->get('system', 'imap_disabled'))));
|
||||||
|
$newuser_private = $config->get('system', 'newuser_private');
|
||||||
|
|
||||||
|
$tpl = Renderer::getMarkupTemplate('welcome.tpl');
|
||||||
|
|
||||||
|
return Renderer::replaceMacros($tpl, [
|
||||||
|
'$welcome' => L10n::t('Welcome to Friendica'),
|
||||||
|
'$checklist' => L10n::t('New Member Checklist'),
|
||||||
|
'$description' => L10n::t('We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page. A link to this page will be visible from your home page for two weeks after your initial registration and then will quietly disappear.'),
|
||||||
|
|
||||||
|
'$started' => L10n::t('Getting Started'),
|
||||||
|
'$quickstart_link' => L10n::t('Friendica Walk-Through'),
|
||||||
|
'$quickstart_txt' => L10n::t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.'),
|
||||||
|
|
||||||
|
'$settings' => L10n::t('Settings'),
|
||||||
|
'$settings_link' => L10n::t('Go to Your Settings'),
|
||||||
|
'$settings_txt' => L10n::t('On your <em>Settings</em> page - change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.'),
|
||||||
|
'$settings_other' => L10n::t('Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you.'),
|
||||||
|
|
||||||
|
'$profile' => L10n::t('Profile'),
|
||||||
|
'$profile_photo_link' => L10n::t('Upload Profile Photo'),
|
||||||
|
'$profile_photo_txt' => L10n::t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.'),
|
||||||
|
'$profiles_link' => L10n::t('Edit Your Profile'),
|
||||||
|
'$profiles_txt' => L10n::t('Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.'),
|
||||||
|
'$profiles_keywords_link' => L10n::t('Profile Keywords'),
|
||||||
|
'$profiles_keywords_txt' => L10n::t('Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships.'),
|
||||||
|
|
||||||
|
'$connecting' => L10n::t('Connecting'),
|
||||||
|
'$mail_disabled' => $mail_disabled,
|
||||||
|
'$import_mail_link' => L10n::t('Importing Emails'),
|
||||||
|
'$import_mail_txt' => L10n::t('Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX'),
|
||||||
|
'$contact_link' => L10n::t('Go to Your Contacts Page'),
|
||||||
|
'$contact_txt' => L10n::t('Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Add New Contact</em> dialog.'),
|
||||||
|
'$directory_link' => L10n::t('Go to Your Site\'s Directory'),
|
||||||
|
'$directory_txt' => L10n::t('The Directory page lets you find other people in this network or other federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on their profile page. Provide your own Identity Address if requested.'),
|
||||||
|
'$finding_link' => L10n::t('Finding New People'),
|
||||||
|
'$finding_txt' => L10n::t('On the side panel of the Contacts page are several tools to find new friends. We can match people by interest, look up people by name or interest, and provide suggestions based on network relationships. On a brand new site, friend suggestions will usually begin to be populated within 24 hours.'),
|
||||||
|
|
||||||
|
'$groups' => L10n::t('Groups'),
|
||||||
|
'$group_contact_link' => L10n::t('Group Your Contacts'),
|
||||||
|
'$group_contact_txt' => L10n::t('Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page.'),
|
||||||
|
'$newuser_private' => $newuser_private,
|
||||||
|
'$private_link' => L10n::t('Why Aren\'t My Posts Public?'),
|
||||||
|
'$private_txt' => L10n::t('Friendica respects your privacy. By default, your posts will only show up to people you\'ve added as friends. For more information, see the help section from the link above.'),
|
||||||
|
|
||||||
|
'$help' => L10n::t('Getting Help'),
|
||||||
|
'$help_link' => L10n::t('Go to the Help Section'),
|
||||||
|
'$help_txt' => L10n::t('Our <strong>help</strong> pages may be consulted for detail on other program features and resources.'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,11 @@ namespace Friendica\Module;
|
||||||
|
|
||||||
use Friendica\BaseModule;
|
use Friendica\BaseModule;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Protocol\Salmon;
|
use Friendica\Protocol\Salmon;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
|
@ -61,67 +63,69 @@ class Xrd extends BaseModule
|
||||||
throw new \Friendica\Network\HTTPException\NotFoundException();
|
throw new \Friendica\Network\HTTPException\NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$profileURL = $app->getBaseURL() . '/profile/' . $user['nickname'];
|
$owner = User::getOwnerDataById($user['uid']);
|
||||||
$alias = str_replace('/profile/', '/~', $profileURL);
|
|
||||||
|
|
||||||
$addr = 'acct:' . $user['nickname'] . '@' . $app->getHostName();
|
$alias = str_replace('/profile/', '/~', $owner['url']);
|
||||||
if ($app->getURLPath()) {
|
|
||||||
$addr .= '/' . $app->getURLPath();
|
$avatar = Photo::selectFirst(['type'], ['uid' => $owner['uid'], 'profile' => true]);
|
||||||
|
|
||||||
|
if (!DBA::isResult($avatar)) {
|
||||||
|
$avatar = ['type' => 'image/jpeg'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mode == 'xml') {
|
if ($mode == 'xml') {
|
||||||
self::printXML($addr, $alias, $profileURL, $app->getBaseURL(), $user);
|
self::printXML($alias, $app->getBaseURL(), $user, $owner, $avatar);
|
||||||
} else {
|
} else {
|
||||||
self::printJSON($addr, $alias, $profileURL, $app->getBaseURL(), $user);
|
self::printJSON($alias, $app->getBaseURL(), $owner, $avatar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function printJSON($uri, $alias, $orofileURL, $baseURL, $user)
|
private static function printJSON($alias, $baseURL, $owner, $avatar)
|
||||||
{
|
{
|
||||||
$salmon_key = Salmon::salmonKey($user['spubkey']);
|
$salmon_key = Salmon::salmonKey($owner['spubkey']);
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
header('Content-type: application/json; charset=utf-8');
|
header('Content-type: application/json; charset=utf-8');
|
||||||
|
|
||||||
$json = [
|
$json = [
|
||||||
'subject' => $uri,
|
'subject' => 'acct:' . $owner['addr'],
|
||||||
'aliases' => [
|
'aliases' => [
|
||||||
$alias,
|
$alias,
|
||||||
$orofileURL,
|
$owner['url'],
|
||||||
],
|
],
|
||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'rel' => NAMESPACE_DFRN,
|
'rel' => NAMESPACE_DFRN,
|
||||||
'href' => $orofileURL,
|
'href' => $owner['url'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => NAMESPACE_FEED,
|
'rel' => NAMESPACE_FEED,
|
||||||
'type' => 'application/atom+xml',
|
'type' => 'application/atom+xml',
|
||||||
'href' => $baseURL . '/dfrn_poll/' . $user['nickname'],
|
'href' => $owner['poll'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://webfinger.net/rel/profile-page',
|
'rel' => 'http://webfinger.net/rel/profile-page',
|
||||||
'type' => 'text/html',
|
'type' => 'text/html',
|
||||||
'href' => $orofileURL,
|
'href' => $owner['url'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'self',
|
'rel' => 'self',
|
||||||
'type' => 'application/activity+json',
|
'type' => 'application/activity+json',
|
||||||
'href' => $orofileURL,
|
'href' => $owner['url'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://microformats.org/profile/hcard',
|
'rel' => 'http://microformats.org/profile/hcard',
|
||||||
'type' => 'text/html',
|
'type' => 'text/html',
|
||||||
'href' => $baseURL . '/hcard/' . $user['nickname'],
|
'href' => $baseURL . '/hcard/' . $owner['nickname'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => NAMESPACE_POCO,
|
'rel' => NAMESPACE_POCO,
|
||||||
'href' => $baseURL . '/poco/' . $user['nickname'],
|
'href' => $owner['poco'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://webfinger.net/rel/avatar',
|
'rel' => 'http://webfinger.net/rel/avatar',
|
||||||
'type' => 'image/jpeg',
|
'type' => $avatar['type'],
|
||||||
'href' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
|
'href' => $owner['photo'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://joindiaspora.com/seed_location',
|
'rel' => 'http://joindiaspora.com/seed_location',
|
||||||
|
@ -130,15 +134,15 @@ class Xrd extends BaseModule
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'salmon',
|
'rel' => 'salmon',
|
||||||
'href' => $baseURL . '/salmon/' . $user['nickname'],
|
'href' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
|
'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
|
||||||
'href' => $baseURL . '/salmon/' . $user['nickname'],
|
'href' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
|
'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
|
||||||
'href' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
|
'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
|
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
|
||||||
|
@ -160,9 +164,9 @@ class Xrd extends BaseModule
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function printXML($uri, $alias, $profileURL, $baseURL, $user)
|
private static function printXML($alias, $baseURL, $user, $owner, $avatar)
|
||||||
{
|
{
|
||||||
$salmon_key = Salmon::salmonKey($user['spubkey']);
|
$salmon_key = Salmon::salmonKey($owner['spubkey']);
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
header('Content-type: text/xml');
|
header('Content-type: text/xml');
|
||||||
|
@ -170,16 +174,17 @@ class Xrd extends BaseModule
|
||||||
$tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
|
$tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
|
||||||
|
|
||||||
$o = Renderer::replaceMacros($tpl, [
|
$o = Renderer::replaceMacros($tpl, [
|
||||||
'$nick' => $user['nickname'],
|
'$nick' => $owner['nickname'],
|
||||||
'$accturi' => $uri,
|
'$accturi' => 'acct:' . $owner['addr'],
|
||||||
'$alias' => $alias,
|
'$alias' => $alias,
|
||||||
'$profile_url' => $profileURL,
|
'$profile_url' => $owner['url'],
|
||||||
'$hcard_url' => $baseURL . '/hcard/' . $user['nickname'],
|
'$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'],
|
||||||
'$atom' => $baseURL . '/dfrn_poll/' . $user['nickname'],
|
'$atom' => $owner['poll'],
|
||||||
'$poco_url' => $baseURL . '/poco/' . $user['nickname'],
|
'$poco_url' => $owner['poco'],
|
||||||
'$photo' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
|
'$photo' => $owner['photo'],
|
||||||
'$salmon' => $baseURL . '/salmon/' . $user['nickname'],
|
'$type' => $avatar['type'],
|
||||||
'$salmen' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
|
'$salmon' => $baseURL . '/salmon/' . $owner['nickname'],
|
||||||
|
'$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
|
||||||
'$subscribe' => $baseURL . '/follow?url={uri}',
|
'$subscribe' => $baseURL . '/follow?url={uri}',
|
||||||
'$openwebauth' => $baseURL . '/owa',
|
'$openwebauth' => $baseURL . '/owa',
|
||||||
'$modexp' => 'data:application/magic-public-key,' . $salmon_key
|
'$modexp' => 'data:application/magic-public-key,' . $salmon_key
|
||||||
|
|
|
@ -109,12 +109,11 @@ class Probe
|
||||||
$url = "http://".$host."/.well-known/host-meta";
|
$url = "http://".$host."/.well-known/host-meta";
|
||||||
|
|
||||||
$xrd_timeout = Config::get('system', 'xrd_timeout', 20);
|
$xrd_timeout = Config::get('system', 'xrd_timeout', 20);
|
||||||
$redirects = 0;
|
|
||||||
|
|
||||||
Logger::log("Probing for ".$host, Logger::DEBUG);
|
Logger::log("Probing for ".$host, Logger::DEBUG);
|
||||||
$xrd = null;
|
$xrd = null;
|
||||||
|
|
||||||
$curlResult = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
|
$curlResult = Network::curl($ssl_url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
|
||||||
if ($curlResult->isSuccess()) {
|
if ($curlResult->isSuccess()) {
|
||||||
$xml = $curlResult->getBody();
|
$xml = $curlResult->getBody();
|
||||||
$xrd = XML::parseString($xml, false);
|
$xrd = XML::parseString($xml, false);
|
||||||
|
@ -122,7 +121,7 @@ class Probe
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_object($xrd)) {
|
if (!is_object($xrd)) {
|
||||||
$curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
|
$curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
|
||||||
if ($curlResult->isTimeout()) {
|
if ($curlResult->isTimeout()) {
|
||||||
Logger::log("Probing timeout for " . $url, Logger::DEBUG);
|
Logger::log("Probing timeout for " . $url, Logger::DEBUG);
|
||||||
self::$istimeout = true;
|
self::$istimeout = true;
|
||||||
|
@ -199,7 +198,7 @@ class Probe
|
||||||
|
|
||||||
$links = self::lrdd($webbie);
|
$links = self::lrdd($webbie);
|
||||||
Logger::log('webfingerDfrn: '.$webbie.':'.print_r($links, true), Logger::DATA);
|
Logger::log('webfingerDfrn: '.$webbie.':'.print_r($links, true), Logger::DATA);
|
||||||
if (count($links)) {
|
if (!empty($links) && is_array($links)) {
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if ($link['@attributes']['rel'] === NAMESPACE_DFRN) {
|
if ($link['@attributes']['rel'] === NAMESPACE_DFRN) {
|
||||||
$profile_link = $link['@attributes']['href'];
|
$profile_link = $link['@attributes']['href'];
|
||||||
|
@ -738,9 +737,8 @@ class Probe
|
||||||
private static function webfinger($url, $type)
|
private static function webfinger($url, $type)
|
||||||
{
|
{
|
||||||
$xrd_timeout = Config::get('system', 'xrd_timeout', 20);
|
$xrd_timeout = Config::get('system', 'xrd_timeout', 20);
|
||||||
$redirects = 0;
|
|
||||||
|
|
||||||
$curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
|
$curlResult = Network::curl($url, false, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
|
||||||
if ($curlResult->isTimeout()) {
|
if ($curlResult->isTimeout()) {
|
||||||
self::$istimeout = true;
|
self::$istimeout = true;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -781,7 +781,7 @@ class Image
|
||||||
$data = Cache::get($url);
|
$data = Cache::get($url);
|
||||||
|
|
||||||
if (is_null($data) || !$data || !is_array($data)) {
|
if (is_null($data) || !$data || !is_array($data)) {
|
||||||
$img_str = Network::fetchUrl($url, true, $redirects, 4);
|
$img_str = Network::fetchUrl($url, true, 4);
|
||||||
|
|
||||||
if (!$img_str) {
|
if (!$img_str) {
|
||||||
return false;
|
return false;
|
||||||
|
|
147
src/Object/Search/ContactResult.php
Normal file
147
src/Object/Search/ContactResult.php
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Object\Search;
|
||||||
|
|
||||||
|
use Friendica\Model\Search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A search result for contact searching
|
||||||
|
*
|
||||||
|
* @see Search for details
|
||||||
|
*/
|
||||||
|
class ContactResult implements IResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $cid;
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $pCid;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $addr;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $item;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $url;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $photo;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $tags;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $network;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCid()
|
||||||
|
{
|
||||||
|
return $this->cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPCid()
|
||||||
|
{
|
||||||
|
return $this->pCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAddr()
|
||||||
|
{
|
||||||
|
return $this->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getItem()
|
||||||
|
{
|
||||||
|
return $this->item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl()
|
||||||
|
{
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPhoto()
|
||||||
|
{
|
||||||
|
return $this->photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTags()
|
||||||
|
{
|
||||||
|
return $this->tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getNetwork()
|
||||||
|
{
|
||||||
|
return $this->network;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param string $addr
|
||||||
|
* @param string $item
|
||||||
|
* @param string $url
|
||||||
|
* @param string $photo
|
||||||
|
* @param string $network
|
||||||
|
* @param int $cid
|
||||||
|
* @param int $pCid
|
||||||
|
* @param string $tags
|
||||||
|
*/
|
||||||
|
public function __construct($name, $addr, $item, $url, $photo, $network, $cid = 0, $pCid = 0, $tags = '')
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->addr = $addr;
|
||||||
|
$this->item = $item;
|
||||||
|
$this->url = $url;
|
||||||
|
$this->photo = $photo;
|
||||||
|
$this->network = $network;
|
||||||
|
|
||||||
|
$this->cid = $cid;
|
||||||
|
$this->pCid = $pCid;
|
||||||
|
$this->tags = $tags;
|
||||||
|
}
|
||||||
|
}
|
11
src/Object/Search/IResult.php
Normal file
11
src/Object/Search/IResult.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Object\Search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default interface for each search result
|
||||||
|
*/
|
||||||
|
interface IResult
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
92
src/Object/Search/ResultList.php
Normal file
92
src/Object/Search/ResultList.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Object\Search;
|
||||||
|
|
||||||
|
use Friendica\Model\Search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of search results with metadata
|
||||||
|
*
|
||||||
|
* @see Search for details
|
||||||
|
*/
|
||||||
|
class ResultList
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Page of the result list
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $page;
|
||||||
|
/**
|
||||||
|
* Total count of results
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $total;
|
||||||
|
/**
|
||||||
|
* items per page
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $itemsPage;
|
||||||
|
/**
|
||||||
|
* Array of results
|
||||||
|
*
|
||||||
|
* @var IResult[]
|
||||||
|
*/
|
||||||
|
private $results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPage()
|
||||||
|
{
|
||||||
|
return $this->page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTotal()
|
||||||
|
{
|
||||||
|
return $this->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getItemsPage()
|
||||||
|
{
|
||||||
|
return $this->itemsPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return IResult[]
|
||||||
|
*/
|
||||||
|
public function getResults()
|
||||||
|
{
|
||||||
|
return $this->results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $page
|
||||||
|
* @param int $total
|
||||||
|
* @param int $itemsPage
|
||||||
|
* @param IResult[] $results
|
||||||
|
*/
|
||||||
|
public function __construct($page = 0, $total = 0, $itemsPage = 0, array $results = [])
|
||||||
|
{
|
||||||
|
$this->page = $page;
|
||||||
|
$this->total = $total;
|
||||||
|
$this->itemsPage = $itemsPage;
|
||||||
|
|
||||||
|
$this->results = $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a result to the result list
|
||||||
|
*
|
||||||
|
* @param IResult $result
|
||||||
|
*/
|
||||||
|
public function addResult(IResult $result)
|
||||||
|
{
|
||||||
|
$this->results[] = $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,7 +74,7 @@ class ActivityPub
|
||||||
return HTTPSignature::fetch($url, $uid);
|
return HTTPSignature::fetch($url, $uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
$curlResult = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']);
|
$curlResult = Network::curl($url, false, ['accept_content' => 'application/activity+json, application/ld+json']);
|
||||||
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,7 @@ class Processor
|
||||||
}
|
}
|
||||||
|
|
||||||
$item['changed'] = DateTimeFormat::utcNow();
|
$item['changed'] = DateTimeFormat::utcNow();
|
||||||
$item['edited'] = $activity['updated'];
|
$item['edited'] = DateTimeFormat::utc($activity['updated']);
|
||||||
|
|
||||||
$item = self::processContent($activity, $item);
|
$item = self::processContent($activity, $item);
|
||||||
if (empty($item)) {
|
if (empty($item)) {
|
||||||
|
@ -198,6 +198,43 @@ class Processor
|
||||||
Item::delete(['uri' => $activity['object_id'], 'owner-id' => $owner]);
|
Item::delete(['uri' => $activity['object_id'], 'owner-id' => $owner]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the item array for an activity
|
||||||
|
*
|
||||||
|
* @param array $activity Activity array
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
public static function addTag($activity)
|
||||||
|
{
|
||||||
|
if (empty($activity['object_content']) || empty($activity['object_id'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($activity['receiver'] as $receiver) {
|
||||||
|
$item = Item::selectFirst(['id', 'tag', 'origin', 'author-link'], ['uri' => $activity['target_id'], 'uid' => $receiver]);
|
||||||
|
if (!DBA::isResult($item)) {
|
||||||
|
// We don't fetch missing content for this purpose
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($item['author-link'] != $activity['actor']) && !$item['origin']) {
|
||||||
|
Logger::info('Not origin, not from the author, skipping update', ['id' => $item['id'], 'author' => $item['author-link'], 'actor' => $activity['actor']]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To-Do:
|
||||||
|
// - Check if "blocktag" is set
|
||||||
|
// - Check if actor is a contact
|
||||||
|
|
||||||
|
if (!stristr($item['tag'], trim($activity['object_content']))) {
|
||||||
|
$tag = $item['tag'] . (strlen($item['tag']) ? ',' : '') . '#[url=' . $activity['object_id'] . ']'. $activity['object_content'] . '[/url]';
|
||||||
|
Item::update(['tag' => $tag], ['id' => $item['id']]);
|
||||||
|
Logger::info('Tagged item', ['id' => $item['id'], 'tag' => $activity['object_content'], 'uri' => $activity['target_id'], 'actor' => $activity['actor']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the item array for an activity
|
* Prepare the item array for an activity
|
||||||
*
|
*
|
||||||
|
@ -333,20 +370,23 @@ class Processor
|
||||||
$item['private'] = !in_array(0, $activity['receiver']);
|
$item['private'] = !in_array(0, $activity['receiver']);
|
||||||
$item['author-link'] = $activity['author'];
|
$item['author-link'] = $activity['author'];
|
||||||
$item['author-id'] = Contact::getIdForURL($activity['author'], 0, true);
|
$item['author-id'] = Contact::getIdForURL($activity['author'], 0, true);
|
||||||
|
$item['owner-link'] = $activity['actor'];
|
||||||
|
$item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
|
||||||
|
|
||||||
if (empty($activity['thread-completion'])) {
|
if (!empty($activity['thread-completion'])) {
|
||||||
$item['owner-link'] = $activity['actor'];
|
// Store the original actor in the "causer" fields to enable the check for ignored or blocked contacts
|
||||||
$item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
|
$item['causer-link'] = $item['owner-link'];
|
||||||
} else {
|
$item['causer-id'] = $item['owner-id'];
|
||||||
Logger::info('Ignoring actor because of thread completion.');
|
|
||||||
|
Logger::info('Ignoring actor because of thread completion.', ['actor' => $item['owner-link']]);
|
||||||
$item['owner-link'] = $item['author-link'];
|
$item['owner-link'] = $item['author-link'];
|
||||||
$item['owner-id'] = $item['author-id'];
|
$item['owner-id'] = $item['author-id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$item['uri'] = $activity['id'];
|
$item['uri'] = $activity['id'];
|
||||||
|
|
||||||
$item['created'] = $activity['published'];
|
$item['created'] = DateTimeFormat::utc($activity['published']);
|
||||||
$item['edited'] = $activity['updated'];
|
$item['edited'] = DateTimeFormat::utc($activity['updated']);
|
||||||
$item['guid'] = $activity['diaspora:guid'];
|
$item['guid'] = $activity['diaspora:guid'];
|
||||||
|
|
||||||
$item = self::processContent($activity, $item);
|
$item = self::processContent($activity, $item);
|
||||||
|
@ -405,8 +445,8 @@ class Processor
|
||||||
*
|
*
|
||||||
* @param array $activity Activity data
|
* @param array $activity Activity data
|
||||||
* @param array $item item array
|
* @param array $item item array
|
||||||
|
* @return int|bool New mail table row id or false on error
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
* @throws \ImagickException
|
|
||||||
*/
|
*/
|
||||||
private static function postMail($activity, $item)
|
private static function postMail($activity, $item)
|
||||||
{
|
{
|
||||||
|
@ -460,7 +500,7 @@ class Processor
|
||||||
}
|
}
|
||||||
$msg['body'] = $item['body'];
|
$msg['body'] = $item['body'];
|
||||||
|
|
||||||
Mail::insert($msg);
|
return Mail::insert($msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -530,7 +570,7 @@ class Processor
|
||||||
DBA::update('contact', ['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]);
|
DBA::update('contact', ['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]);
|
||||||
$contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]);
|
$contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]);
|
||||||
} else {
|
} else {
|
||||||
$contact = false;
|
$contact = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = ['author-id' => Contact::getIdForURL($activity['actor']),
|
$item = ['author-id' => Contact::getIdForURL($activity['actor']),
|
||||||
|
@ -541,7 +581,11 @@ class Processor
|
||||||
// Ensure that the contact has got the right network type
|
// Ensure that the contact has got the right network type
|
||||||
self::switchContact($item['author-id']);
|
self::switchContact($item['author-id']);
|
||||||
|
|
||||||
Contact::addRelationship($owner, $contact, $item, '', false, $note);
|
$result = Contact::addRelationship($owner, $contact, $item, false, $note);
|
||||||
|
if ($result === true) {
|
||||||
|
ActivityPub\Transmitter::sendContactAccept($item['author-link'], $item['author-id'], $owner['uid']);
|
||||||
|
}
|
||||||
|
|
||||||
$cid = Contact::getIdForURL($activity['actor'], $uid);
|
$cid = Contact::getIdForURL($activity['actor'], $uid);
|
||||||
if (empty($cid)) {
|
if (empty($cid)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -194,6 +194,11 @@ class Receiver
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_string($object_id)) {
|
||||||
|
Logger::info('Invalid object id', ['object' => $object_id]);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
$object_type = self::fetchObjectType($activity, $object_id, $uid);
|
$object_type = self::fetchObjectType($activity, $object_id, $uid);
|
||||||
|
|
||||||
// Fetch the content only on activities where this matters
|
// Fetch the content only on activities where this matters
|
||||||
|
@ -217,8 +222,7 @@ class Receiver
|
||||||
|
|
||||||
// We had been able to retrieve the object data - so we can trust the source
|
// We had been able to retrieve the object data - so we can trust the source
|
||||||
$trust_source = true;
|
$trust_source = true;
|
||||||
} elseif (in_array($type, ['as:Like', 'as:Dislike']) ||
|
} elseif (in_array($type, array_merge(self::ACTIVITY_TYPES, ['as:Follow'])) && in_array($object_type, self::CONTENT_TYPES)) {
|
||||||
(($type == 'as:Follow') && in_array($object_type, self::CONTENT_TYPES))) {
|
|
||||||
// Create a mostly empty array out of the activity data (instead of the object).
|
// Create a mostly empty array out of the activity data (instead of the object).
|
||||||
// This way we later don't have to check for the existence of ech individual array element.
|
// This way we later don't have to check for the existence of ech individual array element.
|
||||||
$object_data = self::processObject($activity);
|
$object_data = self::processObject($activity);
|
||||||
|
@ -226,6 +230,13 @@ class Receiver
|
||||||
$object_data['author'] = JsonLD::fetchElement($activity, 'as:actor', '@id');
|
$object_data['author'] = JsonLD::fetchElement($activity, 'as:actor', '@id');
|
||||||
$object_data['object_id'] = $object_id;
|
$object_data['object_id'] = $object_id;
|
||||||
$object_data['object_type'] = ''; // Since we don't fetch the object, we don't know the type
|
$object_data['object_type'] = ''; // Since we don't fetch the object, we don't know the type
|
||||||
|
} elseif (in_array($type, ['as:Add'])) {
|
||||||
|
$object_data = [];
|
||||||
|
$object_data['id'] = JsonLD::fetchElement($activity, '@id');
|
||||||
|
$object_data['target_id'] = JsonLD::fetchElement($activity, 'as:target', '@id');
|
||||||
|
$object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object', '@id');
|
||||||
|
$object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type');
|
||||||
|
$object_data['object_content'] = JsonLD::fetchElement($activity['as:object'], 'as:content', '@type');
|
||||||
} else {
|
} else {
|
||||||
$object_data = [];
|
$object_data = [];
|
||||||
$object_data['id'] = JsonLD::fetchElement($activity, '@id');
|
$object_data['id'] = JsonLD::fetchElement($activity, '@id');
|
||||||
|
@ -366,6 +377,12 @@ class Receiver
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'as:Add':
|
||||||
|
if ($object_data['object_type'] == 'as:tag') {
|
||||||
|
ActivityPub\Processor::addTag($object_data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'as:Announce':
|
case 'as:Announce':
|
||||||
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
|
if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
|
||||||
$profile = APContact::getByURL($object_data['actor']);
|
$profile = APContact::getByURL($object_data['actor']);
|
||||||
|
@ -723,11 +740,11 @@ class Receiver
|
||||||
* @param boolean $trust_source Do we trust the provided object?
|
* @param boolean $trust_source Do we trust the provided object?
|
||||||
* @param integer $uid User ID for the signature that we use to fetch data
|
* @param integer $uid User ID for the signature that we use to fetch data
|
||||||
*
|
*
|
||||||
* @return array with trusted and valid object data
|
* @return array|false with trusted and valid object data
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
* @throws \ImagickException
|
* @throws \ImagickException
|
||||||
*/
|
*/
|
||||||
private static function fetchObject($object_id, $object = [], $trust_source = false, $uid = 0)
|
private static function fetchObject(string $object_id, array $object = [], bool $trust_source = false, int $uid = 0)
|
||||||
{
|
{
|
||||||
// By fetching the type we check if the object is complete.
|
// By fetching the type we check if the object is complete.
|
||||||
$type = JsonLD::fetchElement($object, '@type');
|
$type = JsonLD::fetchElement($object, '@type');
|
||||||
|
@ -766,13 +783,14 @@ class Receiver
|
||||||
|
|
||||||
if ($type == 'as:Announce') {
|
if ($type == 'as:Announce') {
|
||||||
$object_id = JsonLD::fetchElement($object, 'object', '@id');
|
$object_id = JsonLD::fetchElement($object, 'object', '@id');
|
||||||
if (empty($object_id)) {
|
if (empty($object_id) || !is_string($object_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return self::fetchObject($object_id, [], false, $uid);
|
return self::fetchObject($object_id, [], false, $uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::log('Unhandled object type: ' . $type, Logger::DEBUG);
|
Logger::log('Unhandled object type: ' . $type, Logger::DEBUG);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,7 @@ use Friendica\Model\User;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Content\Text\Plaintext;
|
use Friendica\Content\Text\Plaintext;
|
||||||
|
use Friendica\Util\XML;
|
||||||
use Friendica\Util\JsonLD;
|
use Friendica\Util\JsonLD;
|
||||||
use Friendica\Util\LDSignature;
|
use Friendica\Util\LDSignature;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
|
@ -228,11 +229,6 @@ class Transmitter
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// On old installations and never changed contacts this might not be filled
|
|
||||||
if (empty($contact['avatar'])) {
|
|
||||||
$contact['avatar'] = $contact['photo'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = ['@context' => ActivityPub::CONTEXT];
|
$data = ['@context' => ActivityPub::CONTEXT];
|
||||||
$data['id'] = $contact['url'];
|
$data['id'] = $contact['url'];
|
||||||
$data['diaspora:guid'] = $user['guid'];
|
$data['diaspora:guid'] = $user['guid'];
|
||||||
|
@ -253,7 +249,7 @@ class Transmitter
|
||||||
'publicKeyPem' => $user['pubkey']];
|
'publicKeyPem' => $user['pubkey']];
|
||||||
$data['endpoints'] = ['sharedInbox' => System::baseUrl() . '/inbox'];
|
$data['endpoints'] = ['sharedInbox' => System::baseUrl() . '/inbox'];
|
||||||
$data['icon'] = ['type' => 'Image',
|
$data['icon'] = ['type' => 'Image',
|
||||||
'url' => $contact['avatar']];
|
'url' => $contact['photo']];
|
||||||
|
|
||||||
$data['generator'] = self::getService();
|
$data['generator'] = self::getService();
|
||||||
|
|
||||||
|
@ -435,7 +431,7 @@ class Transmitter
|
||||||
$data['to'][] = $profile['url'];
|
$data['to'][] = $profile['url'];
|
||||||
} else {
|
} else {
|
||||||
$data['cc'][] = $profile['url'];
|
$data['cc'][] = $profile['url'];
|
||||||
if (!$item['private']) {
|
if (!$item['private'] && !empty($actor_profile['followers'])) {
|
||||||
$data['cc'][] = $actor_profile['followers'];
|
$data['cc'][] = $actor_profile['followers'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -772,6 +768,8 @@ class Transmitter
|
||||||
$type = 'TentativeAccept';
|
$type = 'TentativeAccept';
|
||||||
} elseif ($item['verb'] == ACTIVITY_FOLLOW) {
|
} elseif ($item['verb'] == ACTIVITY_FOLLOW) {
|
||||||
$type = 'Follow';
|
$type = 'Follow';
|
||||||
|
} elseif ($item['verb'] == ACTIVITY_TAG) {
|
||||||
|
$type = 'Add';
|
||||||
} else {
|
} else {
|
||||||
$type = '';
|
$type = '';
|
||||||
}
|
}
|
||||||
|
@ -875,6 +873,8 @@ class Transmitter
|
||||||
|
|
||||||
if (in_array($data['type'], ['Create', 'Update', 'Delete'])) {
|
if (in_array($data['type'], ['Create', 'Update', 'Delete'])) {
|
||||||
$data['object'] = self::createNote($item);
|
$data['object'] = self::createNote($item);
|
||||||
|
} elseif ($data['type'] == 'Add') {
|
||||||
|
$data = self::createAddTag($item, $data);
|
||||||
} elseif ($data['type'] == 'Announce') {
|
} elseif ($data['type'] == 'Announce') {
|
||||||
$data = self::createAnnounce($item, $data);
|
$data = self::createAnnounce($item, $data);
|
||||||
} elseif ($data['type'] == 'Follow') {
|
} elseif ($data['type'] == 'Follow') {
|
||||||
|
@ -1136,7 +1136,7 @@ class Transmitter
|
||||||
{
|
{
|
||||||
$event = [];
|
$event = [];
|
||||||
$event['name'] = $item['event-summary'];
|
$event['name'] = $item['event-summary'];
|
||||||
$event['content'] = BBCode::convert($item['event-desc'], false, 7);
|
$event['content'] = BBCode::convert($item['event-desc'], false, 9);
|
||||||
$event['startTime'] = DateTimeFormat::utc($item['event-start'] . '+00:00', DateTimeFormat::ATOM);
|
$event['startTime'] = DateTimeFormat::utc($item['event-start'] . '+00:00', DateTimeFormat::ATOM);
|
||||||
|
|
||||||
if (!$item['event-nofinish']) {
|
if (!$item['event-nofinish']) {
|
||||||
|
@ -1226,7 +1226,7 @@ class Transmitter
|
||||||
$regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
|
$regexp = "/[@!]\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
|
||||||
$body = preg_replace_callback($regexp, ['self', 'mentionCallback'], $body);
|
$body = preg_replace_callback($regexp, ['self', 'mentionCallback'], $body);
|
||||||
|
|
||||||
$data['content'] = BBCode::convert($body, false, 7);
|
$data['content'] = BBCode::convert($body, false, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"];
|
$data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"];
|
||||||
|
@ -1251,6 +1251,30 @@ class Transmitter
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an an "add tag" entry
|
||||||
|
*
|
||||||
|
* @param array $item
|
||||||
|
* @param array $data activity data
|
||||||
|
*
|
||||||
|
* @return array with activity data for adding tags
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
private static function createAddTag($item, $data)
|
||||||
|
{
|
||||||
|
$object = XML::parseString($item['object'], false);
|
||||||
|
$target = XML::parseString($item["target"], false);
|
||||||
|
|
||||||
|
$data['diaspora:guid'] = $item['guid'];
|
||||||
|
$data['actor'] = $item['author-link'];
|
||||||
|
$data['target'] = (string)$target->id;
|
||||||
|
$data['summary'] = BBCode::toPlaintext($item['body']);
|
||||||
|
$data['object'] = ['id' => (string)$object->id, 'type' => 'tag', 'name' => (string)$object->title, 'content' => (string)$object->content];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an announce object entry
|
* Creates an announce object entry
|
||||||
*
|
*
|
||||||
|
@ -1450,6 +1474,10 @@ class Transmitter
|
||||||
public static function sendActivity($activity, $target, $uid, $id = '')
|
public static function sendActivity($activity, $target, $uid, $id = '')
|
||||||
{
|
{
|
||||||
$profile = APContact::getByURL($target);
|
$profile = APContact::getByURL($target);
|
||||||
|
if (empty($profile['inbox'])) {
|
||||||
|
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$owner = User::getOwnerDataById($uid);
|
$owner = User::getOwnerDataById($uid);
|
||||||
|
|
||||||
|
@ -1486,6 +1514,10 @@ class Transmitter
|
||||||
public static function sendFollowObject($object, $target, $uid = 0)
|
public static function sendFollowObject($object, $target, $uid = 0)
|
||||||
{
|
{
|
||||||
$profile = APContact::getByURL($target);
|
$profile = APContact::getByURL($target);
|
||||||
|
if (empty($profile['inbox'])) {
|
||||||
|
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($uid)) {
|
if (empty($uid)) {
|
||||||
// Fetch the list of administrators
|
// Fetch the list of administrators
|
||||||
|
@ -1532,19 +1564,26 @@ class Transmitter
|
||||||
public static function sendContactAccept($target, $id, $uid)
|
public static function sendContactAccept($target, $id, $uid)
|
||||||
{
|
{
|
||||||
$profile = APContact::getByURL($target);
|
$profile = APContact::getByURL($target);
|
||||||
|
if (empty($profile['inbox'])) {
|
||||||
|
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$owner = User::getOwnerDataById($uid);
|
$owner = User::getOwnerDataById($uid);
|
||||||
$data = ['@context' => ActivityPub::CONTEXT,
|
$data = ['@context' => ActivityPub::CONTEXT,
|
||||||
'id' => System::baseUrl() . '/activity/' . System::createGUID(),
|
'id' => System::baseUrl() . '/activity/' . System::createGUID(),
|
||||||
'type' => 'Accept',
|
'type' => 'Accept',
|
||||||
'actor' => $owner['url'],
|
'actor' => $owner['url'],
|
||||||
'object' => ['id' => $id, 'type' => 'Follow',
|
'object' => [
|
||||||
|
'id' => (string)$id,
|
||||||
|
'type' => 'Follow',
|
||||||
'actor' => $profile['url'],
|
'actor' => $profile['url'],
|
||||||
'object' => $owner['url']],
|
'object' => $owner['url']
|
||||||
|
],
|
||||||
'instrument' => self::getService(),
|
'instrument' => self::getService(),
|
||||||
'to' => [$profile['url']]];
|
'to' => [$profile['url']]];
|
||||||
|
|
||||||
Logger::log('Sending accept to ' . $target . ' for user ' . $uid . ' with id ' . $id, Logger::DEBUG);
|
Logger::debug('Sending accept to ' . $target . ' for user ' . $uid . ' with id ' . $id);
|
||||||
|
|
||||||
$signed = LDSignature::sign($data, $owner);
|
$signed = LDSignature::sign($data, $owner);
|
||||||
HTTPSignature::transmit($signed, $profile['inbox'], $uid);
|
HTTPSignature::transmit($signed, $profile['inbox'], $uid);
|
||||||
|
@ -1562,19 +1601,26 @@ class Transmitter
|
||||||
public static function sendContactReject($target, $id, $uid)
|
public static function sendContactReject($target, $id, $uid)
|
||||||
{
|
{
|
||||||
$profile = APContact::getByURL($target);
|
$profile = APContact::getByURL($target);
|
||||||
|
if (empty($profile['inbox'])) {
|
||||||
|
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$owner = User::getOwnerDataById($uid);
|
$owner = User::getOwnerDataById($uid);
|
||||||
$data = ['@context' => ActivityPub::CONTEXT,
|
$data = ['@context' => ActivityPub::CONTEXT,
|
||||||
'id' => System::baseUrl() . '/activity/' . System::createGUID(),
|
'id' => System::baseUrl() . '/activity/' . System::createGUID(),
|
||||||
'type' => 'Reject',
|
'type' => 'Reject',
|
||||||
'actor' => $owner['url'],
|
'actor' => $owner['url'],
|
||||||
'object' => ['id' => $id, 'type' => 'Follow',
|
'object' => [
|
||||||
|
'id' => (string)$id,
|
||||||
|
'type' => 'Follow',
|
||||||
'actor' => $profile['url'],
|
'actor' => $profile['url'],
|
||||||
'object' => $owner['url']],
|
'object' => $owner['url']
|
||||||
|
],
|
||||||
'instrument' => self::getService(),
|
'instrument' => self::getService(),
|
||||||
'to' => [$profile['url']]];
|
'to' => [$profile['url']]];
|
||||||
|
|
||||||
Logger::log('Sending reject to ' . $target . ' for user ' . $uid . ' with id ' . $id, Logger::DEBUG);
|
Logger::debug('Sending reject to ' . $target . ' for user ' . $uid . ' with id ' . $id);
|
||||||
|
|
||||||
$signed = LDSignature::sign($data, $owner);
|
$signed = LDSignature::sign($data, $owner);
|
||||||
HTTPSignature::transmit($signed, $profile['inbox'], $uid);
|
HTTPSignature::transmit($signed, $profile['inbox'], $uid);
|
||||||
|
@ -1592,6 +1638,10 @@ class Transmitter
|
||||||
public static function sendContactUndo($target, $cid, $uid)
|
public static function sendContactUndo($target, $cid, $uid)
|
||||||
{
|
{
|
||||||
$profile = APContact::getByURL($target);
|
$profile = APContact::getByURL($target);
|
||||||
|
if (empty($profile['inbox'])) {
|
||||||
|
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$object_id = self::activityIDFromContact($cid);
|
$object_id = self::activityIDFromContact($cid);
|
||||||
if (empty($object_id)) {
|
if (empty($object_id)) {
|
||||||
|
|
|
@ -1229,7 +1229,6 @@ class DFRN
|
||||||
$curlResult = Network::curl($url);
|
$curlResult = Network::curl($url);
|
||||||
|
|
||||||
if ($curlResult->isTimeout()) {
|
if ($curlResult->isTimeout()) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -2; // timed out
|
return -2; // timed out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,29 +1236,24 @@ class DFRN
|
||||||
|
|
||||||
$curl_stat = $curlResult->getReturnCode();
|
$curl_stat = $curlResult->getReturnCode();
|
||||||
if (empty($curl_stat)) {
|
if (empty($curl_stat)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -3; // timed out
|
return -3; // timed out
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::log('dfrn_deliver: ' . $xml, Logger::DATA);
|
Logger::log('dfrn_deliver: ' . $xml, Logger::DATA);
|
||||||
|
|
||||||
if (empty($xml)) {
|
if (empty($xml)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($xml, '<?xml') === false) {
|
if (strpos($xml, '<?xml') === false) {
|
||||||
Logger::log('dfrn_deliver: no valid XML returned');
|
Logger::log('dfrn_deliver: no valid XML returned');
|
||||||
Logger::log('dfrn_deliver: returned XML: ' . $xml, Logger::DATA);
|
Logger::log('dfrn_deliver: returned XML: ' . $xml, Logger::DATA);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = XML::parseString($xml);
|
$res = XML::parseString($xml);
|
||||||
|
|
||||||
if (!is_object($res) || (intval($res->status) != 0) || !strlen($res->challenge) || !strlen($res->dfrn_id)) {
|
if (!is_object($res) || (intval($res->status) != 0) || !strlen($res->challenge) || !strlen($res->dfrn_id)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
|
|
||||||
if (empty($res->status)) {
|
if (empty($res->status)) {
|
||||||
$status = 3;
|
$status = 3;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1315,7 +1309,6 @@ class DFRN
|
||||||
if ($final_dfrn_id != $orig_id) {
|
if ($final_dfrn_id != $orig_id) {
|
||||||
Logger::log('dfrn_deliver: wrong dfrn_id.');
|
Logger::log('dfrn_deliver: wrong dfrn_id.');
|
||||||
// did not decode properly - cannot trust this site
|
// did not decode properly - cannot trust this site
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1351,7 +1344,6 @@ class DFRN
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::log("rino: invalid requested version '$rino_remote_version'");
|
Logger::log("rino: invalid requested version '$rino_remote_version'");
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -8;
|
return -8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,26 +1383,22 @@ class DFRN
|
||||||
|
|
||||||
$curl_stat = $postResult->getReturnCode();
|
$curl_stat = $postResult->getReturnCode();
|
||||||
if (empty($curl_stat) || empty($xml)) {
|
if (empty($curl_stat) || empty($xml)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -9; // timed out
|
return -9; // timed out
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($curl_stat == 503) && stristr($postResult->getHeader(), 'retry-after')) {
|
if (($curl_stat == 503) && stristr($postResult->getHeader(), 'retry-after')) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -10;
|
return -10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($xml, '<?xml') === false) {
|
if (strpos($xml, '<?xml') === false) {
|
||||||
Logger::log('dfrn_deliver: phase 2: no valid XML returned');
|
Logger::log('dfrn_deliver: phase 2: no valid XML returned');
|
||||||
Logger::log('dfrn_deliver: phase 2: returned XML: ' . $xml, Logger::DATA);
|
Logger::log('dfrn_deliver: phase 2: returned XML: ' . $xml, Logger::DATA);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = XML::parseString($xml);
|
$res = XML::parseString($xml);
|
||||||
|
|
||||||
if (!isset($res->status)) {
|
if (!isset($res->status)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -11;
|
return -11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1423,10 +1411,6 @@ class DFRN
|
||||||
Logger::log('Delivery returned status '.$res->status.' - '.$res->message, Logger::DEBUG);
|
Logger::log('Delivery returned status '.$res->status.' - '.$res->message, Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($res->status >= 200) && ($res->status <= 299)) {
|
|
||||||
Contact::unmarkForArchival($contact);
|
|
||||||
}
|
|
||||||
|
|
||||||
return intval($res->status);
|
return intval($res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,7 +1438,6 @@ class DFRN
|
||||||
|
|
||||||
if (empty($contact['addr'])) {
|
if (empty($contact['addr'])) {
|
||||||
Logger::log('Unable to find contact handle for ' . $contact['id'] . ' - ' . $contact['url']);
|
Logger::log('Unable to find contact handle for ' . $contact['id'] . ' - ' . $contact['url']);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -21;
|
return -21;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1462,7 +1445,6 @@ class DFRN
|
||||||
$fcontact = Diaspora::personByHandle($contact['addr']);
|
$fcontact = Diaspora::personByHandle($contact['addr']);
|
||||||
if (empty($fcontact)) {
|
if (empty($fcontact)) {
|
||||||
Logger::log('Unable to find contact details for ' . $contact['id'] . ' - ' . $contact['addr']);
|
Logger::log('Unable to find contact details for ' . $contact['id'] . ' - ' . $contact['addr']);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -22;
|
return -22;
|
||||||
}
|
}
|
||||||
$pubkey = $fcontact['pubkey'];
|
$pubkey = $fcontact['pubkey'];
|
||||||
|
@ -1491,26 +1473,22 @@ class DFRN
|
||||||
$curl_stat = $postResult->getReturnCode();
|
$curl_stat = $postResult->getReturnCode();
|
||||||
if (empty($curl_stat) || empty($xml)) {
|
if (empty($curl_stat) || empty($xml)) {
|
||||||
Logger::log('Empty answer from ' . $contact['id'] . ' - ' . $dest_url);
|
Logger::log('Empty answer from ' . $contact['id'] . ' - ' . $dest_url);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -9; // timed out
|
return -9; // timed out
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($curl_stat == 503) && (stristr($postResult->getHeader(), 'retry-after'))) {
|
if (($curl_stat == 503) && (stristr($postResult->getHeader(), 'retry-after'))) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -10;
|
return -10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($xml, '<?xml') === false) {
|
if (strpos($xml, '<?xml') === false) {
|
||||||
Logger::log('No valid XML returned from ' . $contact['id'] . ' - ' . $dest_url);
|
Logger::log('No valid XML returned from ' . $contact['id'] . ' - ' . $dest_url);
|
||||||
Logger::log('Returned XML: ' . $xml, Logger::DATA);
|
Logger::log('Returned XML: ' . $xml, Logger::DATA);
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = XML::parseString($xml);
|
$res = XML::parseString($xml);
|
||||||
|
|
||||||
if (empty($res->status)) {
|
if (empty($res->status)) {
|
||||||
Contact::markForArchival($contact);
|
|
||||||
return -23;
|
return -23;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,10 +1496,6 @@ class DFRN
|
||||||
Logger::log('Transmit to ' . $dest_url . ' returned status '.$res->status.' - '.$res->message, Logger::DEBUG);
|
Logger::log('Transmit to ' . $dest_url . ' returned status '.$res->status.' - '.$res->message, Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($res->status >= 200) && ($res->status <= 299)) {
|
|
||||||
Contact::unmarkForArchival($contact);
|
|
||||||
}
|
|
||||||
|
|
||||||
return intval($res->status);
|
return intval($res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2242,18 +2216,16 @@ class DFRN
|
||||||
{
|
{
|
||||||
Logger::log("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, Logger::DEBUG);
|
Logger::log("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, Logger::DEBUG);
|
||||||
|
|
||||||
if (($entrytype == DFRN::TOP_LEVEL)) {
|
if (($entrytype == DFRN::TOP_LEVEL) && !empty($importer['id'])) {
|
||||||
// The filling of the the "contact" variable is done for legcy reasons
|
// The filling of the the "contact" variable is done for legcy reasons
|
||||||
// The functions below are partly used by ostatus.php as well - where we have this variable
|
// The functions below are partly used by ostatus.php as well - where we have this variable
|
||||||
$r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"]));
|
$contact = Contact::select([], ['id' => $importer['id']]);
|
||||||
$contact = $r[0];
|
|
||||||
$nickname = $contact["nick"];
|
|
||||||
|
|
||||||
// Big question: Do we need these functions? They were part of the "consume_feed" function.
|
// Big question: Do we need these functions? They were part of the "consume_feed" function.
|
||||||
// This function once was responsible for DFRN and OStatus.
|
// This function once was responsible for DFRN and OStatus.
|
||||||
if (activity_match($item["verb"], ACTIVITY_FOLLOW)) {
|
if (activity_match($item["verb"], ACTIVITY_FOLLOW)) {
|
||||||
Logger::log("New follower");
|
Logger::log("New follower");
|
||||||
Contact::addRelationship($importer, $contact, $item, $nickname);
|
Contact::addRelationship($importer, $contact, $item);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (activity_match($item["verb"], ACTIVITY_UNFOLLOW)) {
|
if (activity_match($item["verb"], ACTIVITY_UNFOLLOW)) {
|
||||||
|
@ -2263,7 +2235,7 @@ class DFRN
|
||||||
}
|
}
|
||||||
if (activity_match($item["verb"], ACTIVITY_REQ_FRIEND)) {
|
if (activity_match($item["verb"], ACTIVITY_REQ_FRIEND)) {
|
||||||
Logger::log("New friend request");
|
Logger::log("New friend request");
|
||||||
Contact::addRelationship($importer, $contact, $item, $nickname, true);
|
Contact::addRelationship($importer, $contact, $item, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (activity_match($item["verb"], ACTIVITY_UNFRIEND)) {
|
if (activity_match($item["verb"], ACTIVITY_UNFRIEND)) {
|
||||||
|
@ -2927,7 +2899,12 @@ class DFRN
|
||||||
{
|
{
|
||||||
// prevent looping
|
// prevent looping
|
||||||
if (!empty($_REQUEST['redir'])) {
|
if (!empty($_REQUEST['redir'])) {
|
||||||
return;
|
Logger::log('autoRedir might be looping because redirect has been redirected', Logger::DEBUG);
|
||||||
|
// looping prevention also appears to sometimes prevent authentication for images
|
||||||
|
// because browser may have multiple connections open and load an image on a connection
|
||||||
|
// whose session wasn't updated when a previous redirect authenticated
|
||||||
|
// Leaving commented in case looping reappears
|
||||||
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((! $contact_nick) || ($contact_nick === $a->user['nickname'])) {
|
if ((! $contact_nick) || ($contact_nick === $a->user['nickname'])) {
|
||||||
|
@ -2951,6 +2928,9 @@ class DFRN
|
||||||
$baseurl = substr($baseurl, $domain_st + 3);
|
$baseurl = substr($baseurl, $domain_st + 3);
|
||||||
$nurl = Strings::normaliseLink($baseurl);
|
$nurl = Strings::normaliseLink($baseurl);
|
||||||
|
|
||||||
|
$r = User::getByNickname($contact_nick, ["uid"]);
|
||||||
|
$contact_uid = $r["uid"];
|
||||||
|
|
||||||
/// @todo Why is there a query for "url" *and* "nurl"? Especially this normalising is strange.
|
/// @todo Why is there a query for "url" *and* "nurl"? Especially this normalising is strange.
|
||||||
$r = q("SELECT `id` FROM `contact` WHERE `uid` = (SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1)
|
$r = q("SELECT `id` FROM `contact` WHERE `uid` = (SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1)
|
||||||
AND `nick` = '%s' AND NOT `self` AND (`url` LIKE '%%%s%%' OR `nurl` LIKE '%%%s%%') AND NOT `blocked` AND NOT `pending` LIMIT 1",
|
AND `nick` = '%s' AND NOT `self` AND (`url` LIKE '%%%s%%' OR `nurl` LIKE '%%%s%%') AND NOT `blocked` AND NOT `pending` LIMIT 1",
|
||||||
|
@ -2959,9 +2939,19 @@ class DFRN
|
||||||
DBA::escape($baseurl),
|
DBA::escape($baseurl),
|
||||||
DBA::escape($nurl)
|
DBA::escape($nurl)
|
||||||
);
|
);
|
||||||
if ((! DBA::isResult($r)) || $r[0]['id'] == remote_user()) {
|
if ((! DBA::isResult($r))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// test if redirect authentication already succeeded
|
||||||
|
// Note that "contact" in the sense used in the $contact_nick argument to this function
|
||||||
|
// and the sense in the $remote[]["cid"] in the session are opposite.
|
||||||
|
// In the session variable the user currently fetching is the contact
|
||||||
|
// while $contact_nick is the nick of tho user who owns the stuff being fetched.
|
||||||
|
foreach (\Friendica\Core\Session::get('remote', []) as $visitor) {
|
||||||
|
if ($visitor['uid'] == $contact_uid && $visitor['cid'] == $r[0]['id']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$r = q("SELECT * FROM contact WHERE nick = '%s'
|
$r = q("SELECT * FROM contact WHERE nick = '%s'
|
||||||
AND network = '%s' AND uid = %d AND url LIKE '%%%s%%' LIMIT 1",
|
AND network = '%s' AND uid = %d AND url LIKE '%%%s%%' LIMIT 1",
|
||||||
|
|
|
@ -37,6 +37,7 @@ use Friendica\Util\Map;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Util\XML;
|
use Friendica\Util\XML;
|
||||||
|
use Friendica\Worker\Delivery;
|
||||||
use SimpleXMLElement;
|
use SimpleXMLElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,7 +145,7 @@ class Diaspora
|
||||||
*/
|
*/
|
||||||
private static function getRelayContact($server_url)
|
private static function getRelayContact($server_url)
|
||||||
{
|
{
|
||||||
$fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked'];
|
$fields = ['batch', 'id', 'name', 'network', 'protocol', 'archive', 'blocked'];
|
||||||
|
|
||||||
// Fetch the relay contact
|
// Fetch the relay contact
|
||||||
$condition = ['uid' => 0, 'nurl' => Strings::normaliseLink($server_url),
|
$condition = ['uid' => 0, 'nurl' => Strings::normaliseLink($server_url),
|
||||||
|
@ -2147,13 +2148,9 @@ class Diaspora
|
||||||
if ($comment['id'] == $comment['parent']) {
|
if ($comment['id'] == $comment['parent']) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($comment['verb'] == ACTIVITY_POST) {
|
|
||||||
$cmd = $comment['self'] ? 'comment-new' : 'comment-import';
|
Logger::info('Deliver participation', ['item' => $comment['id'], 'contact' => $contact_id]);
|
||||||
} else {
|
Worker::add(PRIORITY_HIGH, 'Delivery', Delivery::POST, $comment['id'], $contact_id);
|
||||||
$cmd = $comment['self'] ? 'like' : 'comment-import';
|
|
||||||
}
|
|
||||||
Logger::log("Send ".$cmd." for item ".$comment['id']." to contact ".$contact_id, Logger::DEBUG);
|
|
||||||
Worker::add(PRIORITY_HIGH, 'Delivery', $cmd, $comment['id'], $contact_id);
|
|
||||||
}
|
}
|
||||||
DBA::close($comments);
|
DBA::close($comments);
|
||||||
|
|
||||||
|
@ -3110,13 +3107,12 @@ class Diaspora
|
||||||
* @param string $envelope The message that is to be transmitted
|
* @param string $envelope The message that is to be transmitted
|
||||||
* @param bool $public_batch Is it a public post?
|
* @param bool $public_batch Is it a public post?
|
||||||
* @param string $guid message guid
|
* @param string $guid message guid
|
||||||
* @param bool $no_defer Don't defer a failing delivery
|
|
||||||
*
|
*
|
||||||
* @return int Result of the transmission
|
* @return int Result of the transmission
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
* @throws \ImagickException
|
* @throws \ImagickException
|
||||||
*/
|
*/
|
||||||
public static function transmit(array $owner, array $contact, $envelope, $public_batch, $guid = "", $no_defer = false)
|
private static function transmit(array $owner, array $contact, $envelope, $public_batch, $guid = "")
|
||||||
{
|
{
|
||||||
$enabled = intval(Config::get("system", "diaspora_enabled"));
|
$enabled = intval(Config::get("system", "diaspora_enabled"));
|
||||||
if (!$enabled) {
|
if (!$enabled) {
|
||||||
|
@ -3155,20 +3151,6 @@ class Diaspora
|
||||||
|
|
||||||
Logger::log("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
|
Logger::log("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
|
||||||
|
|
||||||
if (!$return_code || (($return_code == 503) && (stristr($postResult->getHeader(), "retry-after")))) {
|
|
||||||
if (!$no_defer && !empty($contact['contact-type']) && ($contact['contact-type'] != Contact::TYPE_RELAY)) {
|
|
||||||
Logger::info('defer message', ['log' => $logid, 'guid' => $guid, 'destination' => $dest_url]);
|
|
||||||
// defer message for redelivery
|
|
||||||
Worker::defer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The message could not be delivered. We mark the contact as "dead"
|
|
||||||
Contact::markForArchival($contact);
|
|
||||||
} elseif (($return_code >= 200) && ($return_code <= 299)) {
|
|
||||||
// We successfully delivered a message, the contact is alive
|
|
||||||
Contact::unmarkForArchival($contact);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return_code ? $return_code : -1;
|
return $return_code ? $return_code : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3197,13 +3179,12 @@ class Diaspora
|
||||||
* @param array $message The message data
|
* @param array $message The message data
|
||||||
* @param bool $public_batch Is it a public post?
|
* @param bool $public_batch Is it a public post?
|
||||||
* @param string $guid message guid
|
* @param string $guid message guid
|
||||||
* @param bool $no_defer Don't defer a failing delivery
|
|
||||||
*
|
*
|
||||||
* @return int Result of the transmission
|
* @return int Result of the transmission
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
* @throws \ImagickException
|
* @throws \ImagickException
|
||||||
*/
|
*/
|
||||||
private static function buildAndTransmit(array $owner, array $contact, $type, $message, $public_batch = false, $guid = "", $no_defer = false)
|
private static function buildAndTransmit(array $owner, array $contact, $type, $message, $public_batch = false, $guid = "")
|
||||||
{
|
{
|
||||||
$msg = self::buildPostXml($type, $message);
|
$msg = self::buildPostXml($type, $message);
|
||||||
|
|
||||||
|
@ -3217,7 +3198,7 @@ class Diaspora
|
||||||
|
|
||||||
$envelope = self::buildMessage($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
|
$envelope = self::buildMessage($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
|
||||||
|
|
||||||
$return_code = self::transmit($owner, $contact, $envelope, $public_batch, $guid, $no_defer);
|
$return_code = self::transmit($owner, $contact, $envelope, $public_batch, $guid);
|
||||||
|
|
||||||
Logger::log("guid: ".$guid." result ".$return_code, Logger::DEBUG);
|
Logger::log("guid: ".$guid." result ".$return_code, Logger::DEBUG);
|
||||||
|
|
||||||
|
@ -3562,6 +3543,7 @@ class Diaspora
|
||||||
$public = ($item["private"] ? "false" : "true");
|
$public = ($item["private"] ? "false" : "true");
|
||||||
|
|
||||||
$created = DateTimeFormat::utc($item["created"], DateTimeFormat::ATOM);
|
$created = DateTimeFormat::utc($item["created"], DateTimeFormat::ATOM);
|
||||||
|
$edited = DateTimeFormat::utc($item["edited"] ?? $item["created"], DateTimeFormat::ATOM);
|
||||||
|
|
||||||
// Detect a share element and do a reshare
|
// Detect a share element and do a reshare
|
||||||
if (!$item['private'] && ($ret = self::isReshare($item["body"]))) {
|
if (!$item['private'] && ($ret = self::isReshare($item["body"]))) {
|
||||||
|
@ -3616,6 +3598,7 @@ class Diaspora
|
||||||
$message = ["author" => $myaddr,
|
$message = ["author" => $myaddr,
|
||||||
"guid" => $item["guid"],
|
"guid" => $item["guid"],
|
||||||
"created_at" => $created,
|
"created_at" => $created,
|
||||||
|
"edited_at" => $edited,
|
||||||
"public" => $public,
|
"public" => $public,
|
||||||
"text" => $body,
|
"text" => $body,
|
||||||
"provider_display_name" => $item["app"],
|
"provider_display_name" => $item["app"],
|
||||||
|
@ -3794,11 +3777,13 @@ class Diaspora
|
||||||
|
|
||||||
$text = html_entity_decode(BBCode::toMarkdown($body));
|
$text = html_entity_decode(BBCode::toMarkdown($body));
|
||||||
$created = DateTimeFormat::utc($item["created"], DateTimeFormat::ATOM);
|
$created = DateTimeFormat::utc($item["created"], DateTimeFormat::ATOM);
|
||||||
|
$edited = DateTimeFormat::utc($item["edited"], DateTimeFormat::ATOM);
|
||||||
|
|
||||||
$comment = [
|
$comment = [
|
||||||
"author" => self::myHandle($owner),
|
"author" => self::myHandle($owner),
|
||||||
"guid" => $item["guid"],
|
"guid" => $item["guid"],
|
||||||
"created_at" => $created,
|
"created_at" => $created,
|
||||||
|
"edited_at" => $edited,
|
||||||
"parent_guid" => $toplevel_item["guid"],
|
"parent_guid" => $toplevel_item["guid"],
|
||||||
"text" => $text,
|
"text" => $text,
|
||||||
"author_signature" => ""
|
"author_signature" => ""
|
||||||
|
@ -3834,7 +3819,7 @@ class Diaspora
|
||||||
} elseif (in_array($item["verb"], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
} elseif (in_array($item["verb"], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||||
$message = self::constructLike($item, $owner);
|
$message = self::constructLike($item, $owner);
|
||||||
$type = "like";
|
$type = "like";
|
||||||
} elseif (!in_array($item["verb"], [ACTIVITY_FOLLOW])) {
|
} elseif (!in_array($item["verb"], [ACTIVITY_FOLLOW, ACTIVITY_TAG])) {
|
||||||
$message = self::constructComment($item, $owner);
|
$message = self::constructComment($item, $owner);
|
||||||
$type = "comment";
|
$type = "comment";
|
||||||
}
|
}
|
||||||
|
@ -4211,9 +4196,10 @@ class Diaspora
|
||||||
|
|
||||||
$message = self::createProfileData($uid);
|
$message = self::createProfileData($uid);
|
||||||
|
|
||||||
|
// @ToDo Split this into single worker jobs
|
||||||
foreach ($recips as $recip) {
|
foreach ($recips as $recip) {
|
||||||
Logger::log("Send updated profile data for user ".$uid." to contact ".$recip["id"], Logger::DEBUG);
|
Logger::log("Send updated profile data for user ".$uid." to contact ".$recip["id"], Logger::DEBUG);
|
||||||
self::buildAndTransmit($owner, $recip, "profile", $message, false, '', true);
|
self::buildAndTransmit($owner, $recip, "profile", $message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,13 +417,6 @@ class OStatus
|
||||||
$author = self::fetchAuthor($xpath, $entry, $importer, $contact, $stored);
|
$author = self::fetchAuthor($xpath, $entry, $importer, $contact, $stored);
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = XML::getFirstNodeValue($xpath, 'atom:author/poco:preferredUsername/text()', $entry);
|
|
||||||
if ($value != "") {
|
|
||||||
$nickname = $value;
|
|
||||||
} else {
|
|
||||||
$nickname = $author["author-name"];
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = array_merge($header, $author);
|
$item = array_merge($header, $author);
|
||||||
|
|
||||||
$item["uri"] = XML::getFirstNodeValue($xpath, 'atom:id/text()', $entry);
|
$item["uri"] = XML::getFirstNodeValue($xpath, 'atom:id/text()', $entry);
|
||||||
|
@ -463,7 +456,7 @@ class OStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($item["verb"] == ACTIVITY_FOLLOW) {
|
if ($item["verb"] == ACTIVITY_FOLLOW) {
|
||||||
Contact::addRelationship($importer, $contact, $item, $nickname);
|
Contact::addRelationship($importer, $contact, $item);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,7 +738,7 @@ class OStatus
|
||||||
|
|
||||||
self::$conv_list[$conversation] = true;
|
self::$conv_list[$conversation] = true;
|
||||||
|
|
||||||
$curlResult = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
|
$curlResult = Network::curl($conversation, false, ['accept_content' => 'application/atom+xml, text/html']);
|
||||||
|
|
||||||
if (!$curlResult->isSuccess()) {
|
if (!$curlResult->isSuccess()) {
|
||||||
return;
|
return;
|
||||||
|
@ -938,7 +931,7 @@ class OStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
$stored = false;
|
$stored = false;
|
||||||
$curlResult = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
|
$curlResult = Network::curl($related, false, ['accept_content' => 'application/atom+xml, text/html']);
|
||||||
|
|
||||||
if (!$curlResult->isSuccess()) {
|
if (!$curlResult->isSuccess()) {
|
||||||
return;
|
return;
|
||||||
|
@ -1515,7 +1508,7 @@ class OStatus
|
||||||
$author->appendChild($urls);
|
$author->appendChild($urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
XML::addElement($doc, $author, "followers", "", ["url" => System::baseUrl()."/viewcontacts/".$owner["nick"]]);
|
XML::addElement($doc, $author, "followers", "", ["url" => System::baseUrl() . "/profile/" . $owner["nick"] . "/contacts/followers"]);
|
||||||
XML::addElement($doc, $author, "statusnet:profile_info", "", ["local_id" => $owner["uid"]]);
|
XML::addElement($doc, $author, "statusnet:profile_info", "", ["local_id" => $owner["uid"]]);
|
||||||
|
|
||||||
if ($profile["publish"]) {
|
if ($profile["publish"]) {
|
||||||
|
|
|
@ -665,7 +665,7 @@ class PortableContact
|
||||||
$nodeinfo2_url = '';
|
$nodeinfo2_url = '';
|
||||||
|
|
||||||
foreach ($nodeinfo['links'] as $link) {
|
foreach ($nodeinfo['links'] as $link) {
|
||||||
if (!is_array($link) || empty($link['rel'])) {
|
if (!is_array($link) || empty($link['rel']) || empty($link['href'])) {
|
||||||
Logger::log('Invalid nodeinfo format for ' . $server_url, Logger::DEBUG);
|
Logger::log('Invalid nodeinfo format for ' . $server_url, Logger::DEBUG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -749,7 +749,7 @@ class PortableContact
|
||||||
$friendica = false;
|
$friendica = false;
|
||||||
$gnusocial = false;
|
$gnusocial = false;
|
||||||
|
|
||||||
if (is_array($nodeinfo['protocols']['inbound'])) {
|
if (!empty($nodeinfo['protocols']['inbound']) && is_array($nodeinfo['protocols']['inbound'])) {
|
||||||
foreach ($nodeinfo['protocols']['inbound'] as $inbound) {
|
foreach ($nodeinfo['protocols']['inbound'] as $inbound) {
|
||||||
if ($inbound == 'diaspora') {
|
if ($inbound == 'diaspora') {
|
||||||
$diaspora = true;
|
$diaspora = true;
|
||||||
|
@ -1004,7 +1004,7 @@ class PortableContact
|
||||||
$server_url = str_replace("http://", "https://", $server_url);
|
$server_url = str_replace("http://", "https://", $server_url);
|
||||||
|
|
||||||
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
|
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
|
||||||
$curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
|
$curlResult = Network::curl($server_url."/.well-known/host-meta", false, ['timeout' => 20]);
|
||||||
|
|
||||||
// Quit if there is a timeout.
|
// Quit if there is a timeout.
|
||||||
// But we want to make sure to only quit if we are mostly sure that this server url fits.
|
// But we want to make sure to only quit if we are mostly sure that this server url fits.
|
||||||
|
@ -1021,7 +1021,7 @@ class PortableContact
|
||||||
$server_url = str_replace("https://", "http://", $server_url);
|
$server_url = str_replace("https://", "http://", $server_url);
|
||||||
|
|
||||||
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
|
// We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
|
||||||
$curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
|
$curlResult = Network::curl($server_url."/.well-known/host-meta", false, ['timeout' => 20]);
|
||||||
|
|
||||||
// Quit if there is a timeout
|
// Quit if there is a timeout
|
||||||
if ($curlResult->isTimeout()) {
|
if ($curlResult->isTimeout()) {
|
||||||
|
@ -1624,7 +1624,7 @@ class PortableContact
|
||||||
if (!empty($accesstoken)) {
|
if (!empty($accesstoken)) {
|
||||||
$api = 'https://instances.social/api/1.0/instances/list?count=0';
|
$api = 'https://instances.social/api/1.0/instances/list?count=0';
|
||||||
$header = ['Authorization: Bearer '.$accesstoken];
|
$header = ['Authorization: Bearer '.$accesstoken];
|
||||||
$curlResult = Network::curl($api, false, $redirects, ['headers' => $header]);
|
$curlResult = Network::curl($api, false, ['headers' => $header]);
|
||||||
|
|
||||||
if ($curlResult->isSuccess()) {
|
if ($curlResult->isSuccess()) {
|
||||||
$servers = json_decode($curlResult->getBody(), true);
|
$servers = json_decode($curlResult->getBody(), true);
|
||||||
|
|
|
@ -32,10 +32,16 @@ class Emailer
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function send($params)
|
public static function send(array $params)
|
||||||
{
|
{
|
||||||
|
$params['sent'] = false;
|
||||||
|
|
||||||
Hook::callAll('emailer_send_prepare', $params);
|
Hook::callAll('emailer_send_prepare', $params);
|
||||||
|
|
||||||
|
if ($params['sent']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$email_textonly = false;
|
$email_textonly = false;
|
||||||
if (!empty($params['uid'])) {
|
if (!empty($params['uid'])) {
|
||||||
$email_textonly = PConfig::get($params['uid'], "system", "email_textonly");
|
$email_textonly = PConfig::get($params['uid'], "system", "email_textonly");
|
||||||
|
@ -87,11 +93,16 @@ class Emailer
|
||||||
'subject' => $messageSubject,
|
'subject' => $messageSubject,
|
||||||
'body' => $multipartMessageBody,
|
'body' => $multipartMessageBody,
|
||||||
'headers' => $messageHeader,
|
'headers' => $messageHeader,
|
||||||
'parameters' => $sendmail_params
|
'parameters' => $sendmail_params,
|
||||||
|
'sent' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
Hook::callAll("emailer_send", $hookdata);
|
Hook::callAll("emailer_send", $hookdata);
|
||||||
|
|
||||||
|
if ($hookdata['sent']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$res = mail(
|
$res = mail(
|
||||||
$hookdata['to'],
|
$hookdata['to'],
|
||||||
$hookdata['subject'],
|
$hookdata['subject'],
|
||||||
|
|
|
@ -455,7 +455,7 @@ class HTTPSignature
|
||||||
$curl_opts = $opts;
|
$curl_opts = $opts;
|
||||||
$curl_opts['header'] = $headers;
|
$curl_opts['header'] = $headers;
|
||||||
|
|
||||||
$curlResult = Network::curl($request, false, $redirects, $curl_opts);
|
$curlResult = Network::curl($request, false, $curl_opts);
|
||||||
$return_code = $curlResult->getReturnCode();
|
$return_code = $curlResult->getReturnCode();
|
||||||
|
|
||||||
Logger::log('Fetched for user ' . $uid . ' from ' . $request . ' returned ' . $return_code, Logger::DEBUG);
|
Logger::log('Fetched for user ' . $uid . ' from ' . $request . ' returned ' . $return_code, Logger::DEBUG);
|
||||||
|
|
|
@ -68,9 +68,16 @@ class JsonLD
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
$normalized = false;
|
$normalized = false;
|
||||||
Logger::error('normalise error');
|
$messages = [];
|
||||||
// Sooner or later we should log some details as well - but currently this leads to memory issues
|
$currentException = $e;
|
||||||
// Logger::log('normalise error:' . substr(print_r($e, true), 0, 10000), Logger::DEBUG);
|
do {
|
||||||
|
$messages[] = $currentException->getMessage();
|
||||||
|
} while($currentException = $currentException->getPrevious());
|
||||||
|
|
||||||
|
Logger::warning('JsonLD normalize error');
|
||||||
|
Logger::notice('JsonLD normalize error', ['messages' => $messages]);
|
||||||
|
Logger::info('JsonLD normalize error', ['trace' => $e->getTraceAsString()]);
|
||||||
|
Logger::debug('JsonLD normalize error', ['jsonobj' => $jsonobj]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $normalized;
|
return $normalized;
|
||||||
|
|
|
@ -23,19 +23,19 @@ class Network
|
||||||
*
|
*
|
||||||
* @brief Curl wrapper
|
* @brief Curl wrapper
|
||||||
* @param string $url URL to fetch
|
* @param string $url URL to fetch
|
||||||
* @param boolean $binary default false
|
* @param bool $binary default false
|
||||||
* TRUE if asked to return binary results (file download)
|
* TRUE if asked to return binary results (file download)
|
||||||
* @param integer $redirects The recursion counter for internal use - default 0
|
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
|
||||||
* @param integer $timeout Timeout in seconds, default system config value or 60 seconds
|
|
||||||
* @param string $accept_content supply Accept: header with 'accept_content' as the value
|
* @param string $accept_content supply Accept: header with 'accept_content' as the value
|
||||||
* @param string $cookiejar Path to cookie jar file
|
* @param string $cookiejar Path to cookie jar file
|
||||||
|
* @param int $redirects The recursion counter for internal use - default 0
|
||||||
*
|
*
|
||||||
* @return string The fetched content
|
* @return string The fetched content
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function fetchUrl($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
|
public static function fetchUrl(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
|
||||||
{
|
{
|
||||||
$ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar);
|
$ret = self::fetchUrlFull($url, $binary, $timeout, $accept_content, $cookiejar, $redirects);
|
||||||
|
|
||||||
return $ret->getBody();
|
return $ret->getBody();
|
||||||
}
|
}
|
||||||
|
@ -48,26 +48,27 @@ class Network
|
||||||
*
|
*
|
||||||
* @brief Curl wrapper with array of return values.
|
* @brief Curl wrapper with array of return values.
|
||||||
* @param string $url URL to fetch
|
* @param string $url URL to fetch
|
||||||
* @param boolean $binary default false
|
* @param bool $binary default false
|
||||||
* TRUE if asked to return binary results (file download)
|
* TRUE if asked to return binary results (file download)
|
||||||
* @param integer $redirects The recursion counter for internal use - default 0
|
* @param int $timeout Timeout in seconds, default system config value or 60 seconds
|
||||||
* @param integer $timeout Timeout in seconds, default system config value or 60 seconds
|
|
||||||
* @param string $accept_content supply Accept: header with 'accept_content' as the value
|
* @param string $accept_content supply Accept: header with 'accept_content' as the value
|
||||||
* @param string $cookiejar Path to cookie jar file
|
* @param string $cookiejar Path to cookie jar file
|
||||||
|
* @param int $redirects The recursion counter for internal use - default 0
|
||||||
*
|
*
|
||||||
* @return CurlResult With all relevant information, 'body' contains the actual fetched content.
|
* @return CurlResult With all relevant information, 'body' contains the actual fetched content.
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
|
public static function fetchUrlFull(string $url, bool $binary = false, int $timeout = 0, string $accept_content = '', string $cookiejar = '', int &$redirects = 0)
|
||||||
{
|
{
|
||||||
return self::curl(
|
return self::curl(
|
||||||
$url,
|
$url,
|
||||||
$binary,
|
$binary,
|
||||||
$redirects,
|
[
|
||||||
['timeout'=>$timeout,
|
'timeout' => $timeout,
|
||||||
'accept_content'=>$accept_content,
|
'accept_content' => $accept_content,
|
||||||
'cookiejar'=>$cookiejar
|
'cookiejar' => $cookiejar
|
||||||
]
|
],
|
||||||
|
$redirects
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +76,8 @@ class Network
|
||||||
* @brief fetches an URL.
|
* @brief fetches an URL.
|
||||||
*
|
*
|
||||||
* @param string $url URL to fetch
|
* @param string $url URL to fetch
|
||||||
* @param boolean $binary default false
|
* @param bool $binary default false
|
||||||
* TRUE if asked to return binary results (file download)
|
* TRUE if asked to return binary results (file download)
|
||||||
* @param int $redirects The recursion counter for internal use - default 0
|
|
||||||
* @param array $opts (optional parameters) assoziative array with:
|
* @param array $opts (optional parameters) assoziative array with:
|
||||||
* 'accept_content' => supply Accept: header with 'accept_content' as the value
|
* 'accept_content' => supply Accept: header with 'accept_content' as the value
|
||||||
* 'timeout' => int Timeout in seconds, default system config value or 60 seconds
|
* 'timeout' => int Timeout in seconds, default system config value or 60 seconds
|
||||||
|
@ -86,11 +86,12 @@ class Network
|
||||||
* 'nobody' => only return the header
|
* 'nobody' => only return the header
|
||||||
* 'cookiejar' => path to cookie jar file
|
* 'cookiejar' => path to cookie jar file
|
||||||
* 'header' => header array
|
* 'header' => header array
|
||||||
|
* @param int $redirects The recursion counter for internal use - default 0
|
||||||
*
|
*
|
||||||
* @return CurlResult
|
* @return CurlResult
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function curl($url, $binary = false, &$redirects = 0, $opts = [])
|
public static function curl(string $url, bool $binary = false, array $opts = [], int &$redirects = 0)
|
||||||
{
|
{
|
||||||
$stamp1 = microtime(true);
|
$stamp1 = microtime(true);
|
||||||
|
|
||||||
|
@ -227,7 +228,7 @@ class Network
|
||||||
$redirects++;
|
$redirects++;
|
||||||
Logger::log('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
|
Logger::log('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
|
||||||
@curl_close($ch);
|
@curl_close($ch);
|
||||||
return self::curl($curlResponse->getRedirectUrl(), $binary, $redirects, $opts);
|
return self::curl($curlResponse->getRedirectUrl(), $binary, $opts, $redirects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@curl_close($ch);
|
@curl_close($ch);
|
||||||
|
@ -242,14 +243,14 @@ class Network
|
||||||
*
|
*
|
||||||
* @param string $url URL to post
|
* @param string $url URL to post
|
||||||
* @param mixed $params array of POST variables
|
* @param mixed $params array of POST variables
|
||||||
* @param string $headers HTTP headers
|
* @param array $headers HTTP headers
|
||||||
* @param integer $redirects Recursion counter for internal use - default = 0
|
* @param int $redirects Recursion counter for internal use - default = 0
|
||||||
* @param integer $timeout The timeout in seconds, default system config value or 60 seconds
|
* @param int $timeout The timeout in seconds, default system config value or 60 seconds
|
||||||
*
|
*
|
||||||
* @return CurlResult The content
|
* @return CurlResult The content
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
|
public static function post(string $url, $params, array $headers = [], int $timeout = 0, int &$redirects = 0)
|
||||||
{
|
{
|
||||||
$stamp1 = microtime(true);
|
$stamp1 = microtime(true);
|
||||||
|
|
||||||
|
@ -285,7 +286,7 @@ class Network
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined('LIGHTTPD')) {
|
if (defined('LIGHTTPD')) {
|
||||||
if (!is_array($headers)) {
|
if (empty($headers)) {
|
||||||
$headers = ['Expect:'];
|
$headers = ['Expect:'];
|
||||||
} else {
|
} else {
|
||||||
if (!in_array('Expect:', $headers)) {
|
if (!in_array('Expect:', $headers)) {
|
||||||
|
@ -294,7 +295,7 @@ class Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($headers) {
|
if (!empty($headers)) {
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +352,7 @@ class Network
|
||||||
* @return string|boolean The actual working URL, false else
|
* @return string|boolean The actual working URL, false else
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function isUrlValid($url)
|
public static function isUrlValid(string $url)
|
||||||
{
|
{
|
||||||
if (Config::get('system', 'disable_url_validation')) {
|
if (Config::get('system', 'disable_url_validation')) {
|
||||||
return $url;
|
return $url;
|
||||||
|
@ -381,9 +382,8 @@ class Network
|
||||||
*
|
*
|
||||||
* @param string $addr The email address
|
* @param string $addr The email address
|
||||||
* @return boolean True if it's a valid email address, false if it's not
|
* @return boolean True if it's a valid email address, false if it's not
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
|
||||||
*/
|
*/
|
||||||
public static function isEmailDomainValid($addr)
|
public static function isEmailDomainValid(string $addr)
|
||||||
{
|
{
|
||||||
if (Config::get('system', 'disable_email_validation')) {
|
if (Config::get('system', 'disable_email_validation')) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -413,9 +413,8 @@ class Network
|
||||||
*
|
*
|
||||||
* @param string $url URL which get tested
|
* @param string $url URL which get tested
|
||||||
* @return boolean True if url is allowed otherwise return false
|
* @return boolean True if url is allowed otherwise return false
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
|
||||||
*/
|
*/
|
||||||
public static function isUrlAllowed($url)
|
public static function isUrlAllowed(string $url)
|
||||||
{
|
{
|
||||||
$h = @parse_url($url);
|
$h = @parse_url($url);
|
||||||
|
|
||||||
|
@ -460,7 +459,7 @@ class Network
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function isUrlBlocked($url)
|
public static function isUrlBlocked(string $url)
|
||||||
{
|
{
|
||||||
$host = @parse_url($url, PHP_URL_HOST);
|
$host = @parse_url($url, PHP_URL_HOST);
|
||||||
if (!$host) {
|
if (!$host) {
|
||||||
|
@ -491,7 +490,7 @@ class Network
|
||||||
* or if allowed list is not configured
|
* or if allowed list is not configured
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function isEmailDomainAllowed($email)
|
public static function isEmailDomainAllowed(string $email)
|
||||||
{
|
{
|
||||||
$domain = strtolower(substr($email, strpos($email, '@') + 1));
|
$domain = strtolower(substr($email, strpos($email, '@') + 1));
|
||||||
if (!$domain) {
|
if (!$domain) {
|
||||||
|
@ -516,7 +515,7 @@ class Network
|
||||||
* @param array $domain_list
|
* @param array $domain_list
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function isDomainAllowed($domain, array $domain_list)
|
public static function isDomainAllowed(string $domain, array $domain_list)
|
||||||
{
|
{
|
||||||
$found = false;
|
$found = false;
|
||||||
|
|
||||||
|
@ -531,7 +530,7 @@ class Network
|
||||||
return $found;
|
return $found;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function lookupAvatarByEmail($email)
|
public static function lookupAvatarByEmail(string $email)
|
||||||
{
|
{
|
||||||
$avatar['size'] = 300;
|
$avatar['size'] = 300;
|
||||||
$avatar['email'] = $email;
|
$avatar['email'] = $email;
|
||||||
|
@ -554,7 +553,7 @@ class Network
|
||||||
* @param string $url Any user-submitted URL that may contain tracking params
|
* @param string $url Any user-submitted URL that may contain tracking params
|
||||||
* @return string The same URL stripped of tracking parameters
|
* @return string The same URL stripped of tracking parameters
|
||||||
*/
|
*/
|
||||||
public static function stripTrackingQueryParams($url)
|
public static function stripTrackingQueryParams(string $url)
|
||||||
{
|
{
|
||||||
$urldata = parse_url($url);
|
$urldata = parse_url($url);
|
||||||
if (!empty($urldata["query"])) {
|
if (!empty($urldata["query"])) {
|
||||||
|
@ -613,7 +612,7 @@ class Network
|
||||||
* @return string A canonical URL
|
* @return string A canonical URL
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function finalUrl($url, $depth = 1, $fetchbody = false)
|
public static function finalUrl(string $url, int $depth = 1, bool $fetchbody = false)
|
||||||
{
|
{
|
||||||
$a = \get_app();
|
$a = \get_app();
|
||||||
|
|
||||||
|
@ -724,7 +723,7 @@ class Network
|
||||||
* @param string $url2
|
* @param string $url2
|
||||||
* @return string The matching part
|
* @return string The matching part
|
||||||
*/
|
*/
|
||||||
public static function getUrlMatch($url1, $url2)
|
public static function getUrlMatch(string $url1, string $url2)
|
||||||
{
|
{
|
||||||
if (($url1 == "") || ($url2 == "")) {
|
if (($url1 == "") || ($url2 == "")) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -812,7 +811,7 @@ class Network
|
||||||
*
|
*
|
||||||
* @return string The glued URL
|
* @return string The glued URL
|
||||||
*/
|
*/
|
||||||
public static function unparseURL($parsed)
|
public static function unparseURL(array $parsed)
|
||||||
{
|
{
|
||||||
$get = function ($key) use ($parsed) {
|
$get = function ($key) use ($parsed) {
|
||||||
return isset($parsed[$key]) ? $parsed[$key] : null;
|
return isset($parsed[$key]) ? $parsed[$key] : null;
|
||||||
|
@ -844,7 +843,7 @@ class Network
|
||||||
*
|
*
|
||||||
* @return string switched URL
|
* @return string switched URL
|
||||||
*/
|
*/
|
||||||
public static function switchScheme($url)
|
public static function switchScheme(string $url)
|
||||||
{
|
{
|
||||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||||
if (empty($scheme)) {
|
if (empty($scheme)) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue