Browse Source

Merge branch 'master' into develop

pull/7312/head
Hypolite Petovan 2 years ago
parent
commit
b9ab613777
  1. 4
      .gitignore
  2. 42
      CHANGELOG
  3. 11
      CREDITS.txt
  4. 2
      VERSION
  5. 35
      boot.php
  6. 16
      composer.json
  7. 179
      composer.lock
  8. 2
      config/settings.config.php
  9. 2
      doc/Addons.md
  10. 15
      doc/FAQ.md
  11. 8
      include/api.php
  12. 77
      include/items.php
  13. 49
      include/text.php
  14. 2
      mod/cal.php
  15. 2
      mod/dfrn_confirm.php
  16. 6
      mod/dfrn_notify.php
  17. 2
      mod/dfrn_request.php
  18. 265
      mod/dirfind.php
  19. 15
      mod/display.php
  20. 5
      mod/events.php
  21. 3
      mod/fsuggest.php
  22. 17
      mod/item.php
  23. 42
      mod/network.php
  24. 61
      mod/newmember.php
  25. 2
      mod/notes.php
  26. 3
      mod/notifications.php
  27. 13
      mod/parse_url.php
  28. 36
      mod/photos.php
  29. 7
      mod/redir.php
  30. 14
      mod/search.php
  31. 3
      mod/settings.php
  32. 3
      mod/tagger.php
  33. 36
      mod/uexport.php
  34. 2
      mod/videos.php
  35. 120
      mod/viewcontacts.php
  36. 14
      src/App.php
  37. 11
      src/App/Router.php
  38. 14
      src/Console/Typo.php
  39. 2
      src/Content/ForumManager.php
  40. 8
      src/Content/Nav.php
  41. 3
      src/Content/OEmbed.php
  42. 10
      src/Content/Smilies.php
  43. 343
      src/Content/Text/BBCode.php
  44. 149
      src/Content/Widget.php
  45. 2
      src/Content/Widget/ContactBlock.php
  46. 4
      src/Core/ACL.php
  47. 20
      src/Core/Config/Cache/ConfigCache.php
  48. 2
      src/Core/Config/Configuration.php
  49. 2
      src/Core/Installer.php
  50. 244
      src/Core/Search.php
  51. 10
      src/Core/UserImport.php
  52. 4
      src/Core/Worker.php
  53. 69
      src/Database/DBA.php
  54. 3
      src/Factory/DBFactory.php
  55. 37
      src/Factory/LoggerFactory.php
  56. 73
      src/Model/APContact.php
  57. 153
      src/Model/Contact.php
  58. 2
      src/Model/Event.php
  59. 532
      src/Model/FileTag.php
  60. 72
      src/Model/Item.php
  61. 7
      src/Model/Mail.php
  62. 24
      src/Model/Photo.php
  63. 248
      src/Model/Profile.php
  64. 33
      src/Model/User.php
  65. 4
      src/Module/Admin/Federation.php
  66. 6
      src/Module/Admin/Logs/Settings.php
  67. 3
      src/Module/Admin/Site.php
  68. 23
      src/Module/Admin/Summary.php
  69. 24
      src/Module/BaseAdminModule.php
  70. 167
      src/Module/BaseSearchModule.php
  71. 63
      src/Module/Contact.php
  72. 3
      src/Module/Diaspora/Fetch.php
  73. 23
      src/Module/Directory.php
  74. 2
      src/Module/Filer/RemoveTag.php
  75. 5
      src/Module/Filer/SaveTag.php
  76. 34
      src/Module/GnuSocial/Notice.php
  77. 16
      src/Module/Logout.php
  78. 2
      src/Module/Magic.php
  79. 11
      src/Module/Profile.php
  80. 136
      src/Module/Profile/Contacts.php
  81. 32
      src/Module/Search/Directory.php
  82. 69
      src/Module/Welcome.php
  83. 71
      src/Module/Xrd.php
  84. 10
      src/Network/Probe.php
  85. 2
      src/Object/Image.php
  86. 147
      src/Object/Search/ContactResult.php
  87. 11
      src/Object/Search/IResult.php
  88. 92
      src/Object/Search/ResultList.php
  89. 2
      src/Protocol/ActivityPub.php
  90. 68
      src/Protocol/ActivityPub/Processor.php
  91. 28
      src/Protocol/ActivityPub/Receiver.php
  92. 80
      src/Protocol/ActivityPub/Transmitter.php
  93. 58
      src/Protocol/DFRN.php
  94. 44
      src/Protocol/Diaspora.php
  95. 15
      src/Protocol/OStatus.php
  96. 10
      src/Protocol/PortableContact.php
  97. 15
      src/Util/Emailer.php
  98. 2
      src/Util/HTTPSignature.php
  99. 13
      src/Util/JsonLD.php
  100. 75
      src/Util/Network.php

4
.gitignore

@ -6,7 +6,6 @@ favicon.*
*.out
*.version*
home.html
*~
robots.txt
@ -74,3 +73,6 @@ venv/
#ignore filesystem storage default path
/storage
#Ignore log folder
/log

42
CHANGELOG

@ -1,17 +1,20 @@
Version 2019.06 (UNRELEASED) (2019-06-?)
Version 2019.06 (2019-06-23)
Friendica Core:
Update to the tranlation (CS, DE, ET, PL, PT-BR, SV) [translation teams]
Update to the documentation [nupplaphil, realkinetix]
Update to the tranlation (CS, DE, EN-GB, EN-US, ET, FR, IT, PL, PT-BR, SV) [translation teams]
Update to the documentation [nupplaphil, realkinetix, MrPetovan]
Update to the themes (frio, vier) [BinkaDroid, MrPetovan, tobiasd]
Enhancements to the API [annando, MrPetovan]
Enhancements to the way reshares are handled [annando]
Enhancements to the redis configuration [nupplaphil]
Enhancements to the federation stats display in the admin panel [tobiasd]
Enhancements to the processing of changed storage engine [MrPetovan]
Enhancements to ActivityPub support [annando, MrPetovan]
Enhancements to code security [MrPetovan]
Enhancements to delivery counter [annando]
Fixed the notification order [JeroenED]
Fixed the timezone of Friendica logs [nupplaphil]
Fixed tag completion painfully slow [AlfredSK]
Fixed a regression in notifications [MrPetovan]
Fixed a regression in notifications [MrPetovan, annando]
Fixed an issue with smilies and code blocks [MrPetovan]
Fixed an AP issue with unavailable local profiles [MrPetovan]
Fixed an issue with the File to Folder feature [MrPetovan]
@ -20,35 +23,56 @@ Version 2019.06 (UNRELEASED) (2019-06-?)
Fixed an issue occuring when the BasePath was not set [tobiasd]
Fixed an issue with additionally opened Sessions [MrPetovan]
Fixed an issue with legacy loglevel mapping [nupplaphil]
Fixed contact suggestions [annando]
Fixed an issue with frio hovercard [nupplaphil]
Fixed event interaction federation [annando]
Fixed remote image permission [deantownsley]
General Code cleaning and restructuring [annando, nupplaphil, tobiasd]
Added frio color scheme sharing [JeroenED]
Added syslog and stream Logger [nupplaphil]
Added storage move cronjob [MrPetovan]
Added collapsible panel for connector permission fields [MrPetovan]
Added rule-based router [MrPetovan]
Added Estinian translation [Rain Hawk]
Added Estonian translation [Rain Hawk]
Added APCu caching [nupplaphil]
Added BlockServer command to the Friendica console [nupplaphil]
Added reshare count [annando]
Added rule-based router [MrPetovan, nupplaphil]
Added themed error pages with mascot [MrPetovan, lostinlight]
Added contact relationship filter [MrPetovan]
Removed the old queue mechanism (deferred workers are now used) [annando]
Removed BasePath and Hostname settings from the admin panel [nupplaphil]
Remove support for defunct F-Droid Friendica app [MrPetovan]
Friendica Addons:
Update to the tranlation (ET, SV, ZH_CN) [translation teams]
botdetection:
Added a new addon for preventing access by bots [nupplaphil]
Added a new addon for preventing access by bots [nupplaphil, annando]
buffer:
Traces of Google+ were removed [annando]
curweather:
Fixed a problem with the display of the correct temperature unit [tobiasd]
fromgplus:
Deprecated the addon as Google+ was closed [tobiasd]
fortunate:
Deprecated addon for incompatibility with latest Friendica version [MrPetovan]
phpmailer:
Added a new addon to use external SMTP for email [M-arcus]
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:
5011, 5047, 5850, 6303, 6319, 6478, 6319, 6720, 6815, 6864, 6879,
6903, 6921, 6927, 6936, 6941, 6943, 6947, 6948, 6952
1012, 2209, 2528, 3309, 3717, 3816, 3869, 4453, 4999, 5011, 5047, 5276, 5850, 5983, 6303, 6319, 6379, 6410, 6477,
6478, 6720, 6799, 6813, 6819, 6861, 6864, 6879, 6903, 6916, 6917, 6918, 6921, 6927, 6929, 6936, 6938, 6941, 6943,
6947, 6948, 6950, 6952, 6983, 6999, 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)
Friendica Core:
Update to the translation (CS, DE, EN-GB, EN-US, ES, FR, IT, PL, SV, ZH-CN) [translation teams]

11
CREDITS.txt

@ -1,3 +1,5 @@
23n
Abinoam P. Marques Jr.
Abraham Pérez Hernández
@ -26,6 +28,7 @@ Andy Hee
Angristan
Anthronaut
Arian - Cazare Muncitori
Asher Pen
Athalbert
aweiher
axelt
@ -37,6 +40,8 @@ Beluga
Ben
Ben Roberts
ben-utzer
BinkaDroid
Bjoessi
bufalo1973
Calango Jr
Carlos Solís
@ -107,6 +112,7 @@ Jens Tautenhahn
jensp
Jeroen De Meerleer
jeroenpraat
JOduMonT
Johannes Schwab
John Brazil
Jonatan Nyberg
@ -175,6 +181,7 @@ R C
Rabuzarus
Radek
Rafael Garau
Rain Hawk
Rainulf Pineda
Ralf Thees
Ralph
@ -183,6 +190,7 @@ rcmaniac
rebeka-catalina
repat
Ricardo Pereira
Rik 4
RJ Madsen
Roland Häder
Rui Andrada
@ -207,6 +215,7 @@ Steffen K9
StefOfficiel
Sveinn í Felli
Sven Anders
Sylke Vicious
Sylvain Lagacé
szymon.filip
Sérgio Lima
@ -225,6 +234,7 @@ tomacat
tomamplius
tomtom84
Tony Baldwin
Torbjörn Andersson
TORminator
trebor
tschlotfeldt
@ -234,6 +244,7 @@ U-SOUND\mike
ufic
Ulf Rompe
Unknown
Valvin
Vasudev Kamath
Vasya Novikov
Vinzenz Vietzke

2
VERSION

@ -1 +1 @@
2019.06-dev
2019.06

35
boot.php

@ -31,7 +31,7 @@ use Friendica\Util\DateTimeFormat;
define('FRIENDICA_PLATFORM', 'Friendica');
define('FRIENDICA_CODENAME', 'Dalmatian Bellflower');
define('FRIENDICA_VERSION', '2019.06-dev');
define('FRIENDICA_VERSION', '2019.06');
define('DFRN_PROTOCOL_VERSION', '2.23');
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);
}
/**
* @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)
{
$arg_st = strpos($query, '?');

16
composer.json

@ -37,6 +37,7 @@
"mobiledetect/mobiledetectlib": "2.8.*",
"monolog/monolog": "^1.24",
"nikic/fast-route": "^1.3",
"paragonie/hidden-string": "^1.0",
"pear/text_languagedetect": "1.*",
"pragmarx/google2fa": "^5.0",
"pragmarx/recovery": "^0.1.0",
@ -46,6 +47,7 @@
"fxp/composer-asset-plugin": "~1.3",
"bower-asset/base64": "^1.0",
"bower-asset/chart-js": "^2.7",
"bower-asset/dompurify": "^1.0",
"bower-asset/perfect-scrollbar": "^0.6",
"bower-asset/vue": "^2.5",
"npm-asset/jquery": "^2.0",
@ -95,7 +97,19 @@
},
"archive": {
"exclude": [
"log", "cache", "/photo", "/proxy"
"/.*",
"/*file",
"!/.htaccess-dist",
"/tests",
"/*.xml",
"/composer.*",
"/log",
"/cache",
"/photo",
"/proxy",
"/addon",
"!/vendor",
"!/view/asset"
]
},
"require-dev": {

179
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d7302553201de079b72871c0b2922ce7",
"content-hash": "eb985236d64ed0b0fe1fc2e4ac6616e2",
"packages": [
{
"name": "asika/simple-console",
@ -148,6 +148,51 @@
"description": "Base64 encoding and decoding",
"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",
"version": "0.6.16",
@ -1175,6 +1220,22 @@
"require": {
"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",
"extra": {
"npm-asset-bugs": {
@ -1220,6 +1281,14 @@
"reference": null,
"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",
"extra": {
"npm-asset-bugs": {
@ -1253,6 +1322,32 @@
"reference": null,
"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",
"extra": {
"npm-asset-bugs": {
@ -1403,6 +1498,12 @@
"reference": null,
"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",
"extra": {
"npm-asset-bugs": {
@ -1622,25 +1723,24 @@
},
{
"name": "paragonie/constant_time_encoding",
"version": "v1.0.4",
"version": "v2.2.3",
"source": {
"type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6"
"reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
"reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/55af0dc01992b4d0da7f6372e2eac097bbbaffdb",
"reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb",
"shasum": ""
},
"require": {
"php": "^5.3|^7"
"php": "^7"
},
"require-dev": {
"paragonie/random_compat": "^1.4|^2",
"phpunit/phpunit": "4.*|5.*",
"vimeo/psalm": "^0.3|^1"
"phpunit/phpunit": "^6|^7",
"vimeo/psalm": "^1|^2"
},
"type": "library",
"autoload": {
@ -1681,7 +1781,56 @@
"hex2bin",
"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",
@ -3600,7 +3749,7 @@
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
@ -3702,7 +3851,7 @@
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"homepage": "https://github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
@ -3770,7 +3919,7 @@
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"homepage": "https://github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
@ -3822,7 +3971,7 @@
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"homepage": "https://github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
@ -3924,7 +4073,7 @@
}
],
"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"
},
{

2
config/settings.config.php

@ -74,7 +74,7 @@ return [
// logfile (String)
// The logfile for storing logs.
// Can be a full path or a relative path to the Friendica home directory
'logfile' => 'friendica.log',
'logfile' => 'log/friendica.log',
// loglevel (String)
// The loglevel for all logs.

2
doc/Addons.md

@ -358,6 +358,7 @@ Called from `Emailer::send()` before building the mime message.
- **htmlVersion**: html version of the message
- **textVersion**: text only version of the message
- **additionalMailHeader**: additions to the smtp mail header
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
### emailer_send
Called before calling PHP's `mail()`.
@ -367,6 +368,7 @@ Called before calling PHP's `mail()`.
- **subject**
- **body**
- **headers**
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
### load_config
Called during `App` initialization to allow addons to load their own configuration file(s) with `App::loadConfigFile()`.

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.
<a name="removed"></a>
### What happens when an account is removed? Is it truly deleted?
### What happens when an account is removed?
If you delete your account, we will immediately remove all your content on **your** server.
If you remove your account, it will be scheduled for permanent deletion in *seven days*.
As soon as you activate the deletion process you won't be able to login any more.
Only the administrator of your node can halt this process prior to permanent deletion.
Then Friendica issues requests to all your contacts to remove you.
This will also remove you from the global directory.
Doing this requires your account and profile still to be "partially" available for up to 24 hours in order to establish contact with all your friends.
We can block it in several ways so that it appears empty and all profile information erased, but will then wait for 24 hours (or after all of your contacts have been notified) before we can physically remove it.
After that, your account is deleted.
After the elapsed time of seven days, all your posts, messages, photos, and personal information stored on your node will be deleted.
Your node will also issue removal requests to all your contacts; this will also remove your profile from the global directory if you are listed.
Your username cannot be reissued for future sign-ups for security reasons.
<a name="hashtag"></a>
### Can I follow a hashtag?

8
include/api.php

@ -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();
} catch (HTTPException $e) {
header("HTTP/1.1 {$e->getCode()} {$e->httpdesc}");
@ -611,7 +611,7 @@ function api_get_user(App $a, $contact_id = null)
'name' => $contact["name"],
'screen_name' => (($contact['nick']) ? $contact['nick'] : $contact['name']),
'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_https' => $contact["micro"],
'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']),
'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']),
'location' => $location,
'description' => $description,
'description' => HTML::toPlaintext(BBCode::toPlaintext($description)),
'profile_image_url' => $uinfo[0]['micro'],
'profile_image_url_https' => $uinfo[0]['micro'],
'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)
{
$condition = [
'owner-id' => $ownerId,
'author-id'=> $ownerId,
'uid' => $uid,
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'private' => false

77
include/items.php

@ -446,80 +446,3 @@ function drop_item($id, $return = '')
//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;
}

49
include/text.php

@ -8,10 +8,8 @@ use Friendica\Content\Smilies;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Protocol;
use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Util\Strings;
use Friendica\Util\XML;
/**
* Turn user/group ACLs stored as angle bracketed text into arrays
@ -186,21 +184,17 @@ function get_cats_and_terms($item)
{
$categories = [];
$folders = [];
$matches = [];
$first = true;
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
$categories[] = [
'name' => XML::escape(FileTag::decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?'filerm/' . $item['id'] . '?f=&cat=' . XML::escape(FileTag::decode($mtch[1])):""),
'first' => $first,
'last' => false
];
$first = false;
}
foreach (FileTag::fileToArray($item['file'] ?? '', 'category') as $savedFolderName) {
$categories[] = [
'name' => $savedFolderName,
'url' => "#",
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&cat=' . rawurlencode($savedFolderName) : ""),
'first' => $first,
'last' => false
];
$first = false;
}
if (count($categories)) {
@ -208,20 +202,15 @@ function get_cats_and_terms($item)
}
if (local_user() == $item['uid']) {
$matches = [];
$first = true;
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
$folders[] = [
'name' => XML::escape(FileTag::decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&term=' . XML::escape(FileTag::decode($mtch[1])) : ""),
'first' => $first,
'last' => false
];
$first = false;
}
foreach (FileTag::fileToArray($item['file'] ?? '') as $savedFolderName) {
$folders[] = [
'name' => $savedFolderName,
'url' => "#",
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&term=' . rawurlencode($savedFolderName) : ""),
'first' => $first,
'last' => false
];
$first = false;
}
}

2
mod/cal.php

@ -147,7 +147,7 @@ function cal_content(App $a)
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
// 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
if ($mode == 'view') {

2
mod/dfrn_confirm.php

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

6
mod/dfrn_notify.php

@ -190,13 +190,13 @@ function dfrn_dispatch_public($postdata)
}
// Fetch the corresponding public contact
$contact = Contact::getDetailsByAddr($msg['author'], 0);
if (!$contact) {
$contact_id = Contact::getIdForURL($msg['author']);
if (empty($contact_id)) {
Logger::log('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact ' . $msg['author'] . ' not found');
}
$importer = DFRN::getImporter($contact['id']);
$importer = DFRN::getImporter($contact_id);
// This should never fail
if (empty($importer)) {

2
mod/dfrn_request.php

@ -476,7 +476,7 @@ function dfrn_request_post(App $a)
function dfrn_request_content(App $a)
{
if (($a->argc != 2) || (!count($a->profile))) {
if ($a->argc != 2 || empty($a->profile)) {
return "";
}

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;
}

15
mod/display.php

@ -84,6 +84,10 @@ function display_init(App $a)
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')) {
Logger::log('Directly serving XML for id '.$item["id"], Logger::DEBUG);
displayShowFeed($item["id"], false);
@ -186,16 +190,7 @@ function display_fetchauthor($a, $item)
$profiledata["photo"] = System::removedBaseUrl($profiledata["photo"]);
if (local_user()) {
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);
return $profiledata;
}
function display_content(App $a, $update = false, $update_uid = 0)

5
mod/events.php

@ -21,6 +21,7 @@ use Friendica\Module\Login;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
use Friendica\Util\Temporal;
use Friendica\Worker\Delivery;
function events_init(App $a)
{
@ -195,7 +196,7 @@ function events_post(App $a)
$item_id = Event::store($datarray);
if (!$cid) {
Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
Worker::add(PRIORITY_HIGH, "Notifier", Delivery::POST, $item_id);
}
$a->internalRedirect('events');
@ -246,7 +247,7 @@ function events_content(App $a)
$tabs = '';
// tabs
if ($a->theme_events_in_profile) {
$tabs = Profile::getTabs($a, true);
$tabs = Profile::getTabs($a, 'events', true);
}
$mode = 'view';

3
mod/fsuggest.php

@ -10,6 +10,7 @@ use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
function fsuggest_post(App $a)
{
@ -51,7 +52,7 @@ function fsuggest_post(App $a)
'photo' => $contact['avatar'], 'note' => $note, 'created' => DateTimeFormat::utcNow()];
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);
}

17
mod/item.php

@ -27,12 +27,12 @@ use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Model\Attach;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\FileTag;
use Friendica\Model\Item;
use Friendica\Model\Photo;
use Friendica\Model\Attach;
use Friendica\Model\Term;
use Friendica\Protocol\Diaspora;
use Friendica\Protocol\Email;
@ -40,6 +40,7 @@ use Friendica\Util\DateTimeFormat;
use Friendica\Util\Emailer;
use Friendica\Util\Security;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
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
$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
@ -338,10 +338,9 @@ function item_post(App $a) {
$categories = FileTag::listToFile(trim(defaults($_REQUEST, 'category', '')), 'category');
$categories_new = $categories;
if (!empty($filedas))
{
if (!empty($filedas) && is_array($filedas)) {
// append the fileas stuff to the new categories list
$categories .= FileTag::listToFile($filedas, 'file');
$categories .= FileTag::arrayToFile($filedas);
}
// get contact info for poster
@ -605,8 +604,6 @@ function item_post(App $a) {
$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));
// 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.
// These kind of posts don't initiate the notifier call in the item class.
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');

42
mod/network.php

@ -78,9 +78,7 @@ function network_init(App $a)
// convert query string to array. remove friendica args
$query_array = [];
$query_string = str_replace($a->cmd . '?', '', $a->query_string);
parse_str($query_string, $query_array);
array_shift($query_array);
parse_str(parse_url($a->query_string, PHP_URL_QUERY), $query_array);
// fetch last used network view and redirect if needed
if (!$is_a_date_query) {
@ -100,7 +98,7 @@ function network_init(App $a)
if ($remember_tab) {
// 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
$tab_baseurls = [
@ -112,12 +110,12 @@ function network_init(App $a)
'', //bookmarked
];
$tab_args = [
'f=&order=comment', //all
'f=&order=post', //postord
'f=&conv=1', //conv
'order=comment', //all
'order=post', //postord
'conv=1', //conv
'', //new
'f=&star=1', //starred
'f=&bmark=1', //bookmarked
'star=1', //starred
'bmark=1', //bookmarked
];
$k = array_search('active', $last_sel_tabs);
@ -141,7 +139,7 @@ function network_init(App $a)
if ($remember_tab) {
$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);
@ -155,7 +153,7 @@ function network_init(App $a)
$a->page['aside'] .= Group::sidebarWidget('network/0', 'network', 'standard', $group_id);
$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'] .= saved_searches($search);
$a->page['aside'] .= Widget::fileAs('network', defaults($_GET, 'file', '') );
@ -203,12 +201,12 @@ function saved_searches($search)
*
* urls -> returns
* '/network' => $no_active = 'active'
* '/network?f=&order=comment' => $comment_active = 'active'
* '/network?f=&order=post' => $postord_active = 'active'
* '/network?f=&conv=1', => $conv_active = 'active'
* '/network?order=comment' => $comment_active = 'active'
* '/network?order=post' => $postord_active = 'active'
* '/network?conv=1', => $conv_active = 'active'
* '/network/new', => $new_active = 'active'
* '/network?f=&star=1', => $starred_active = 'active'
* '/network?f=&bmark=1', => $bookmarked_active = 'active'
* '/network?star=1', => $starred_active = 'active'
* '/network?bmark=1', => $bookmarked_active = 'active'
*
* @param App $a
* @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 = [
[
'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,
'title' => L10n::t('Sort by Comment Date'),
'id' => 'commented-order-tab',
@ -982,7 +980,7 @@ function network_tabs(App $a)
],
[
'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,
'title' => L10n::t('Sort by Post Date'),
'id' => 'posted-order-tab',
@ -992,7 +990,7 @@ function network_tabs(App $a)
$tabs[] = [
'label' => L10n::t('Personal'),
'url' => str_replace('/new', '', $cmd) . (!empty($_GET['cid']) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
'url' =>