Merge branch '2021.03-rc' into copyright-2021

This commit is contained in:
Balázs Úr 2021-03-29 08:45:21 +02:00 committed by GitHub
commit befc2af504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 41829 additions and 40547 deletions

182
LICENSE
View File

@ -1,23 +1,7 @@
Friendica Communications Server
Copyright (c) 2010-2020 the Friendica Project
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
GNU AFFERO GENERAL PUBLIC LICENSE GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007 Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -100,7 +84,7 @@ computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the distribution (with or without modification), making available to the
public, and in some countries other activities as well. public, and in some countries other activities as well.
To "convey" a wok means any kind of propagation that enables other To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying. a computer network, with no transfer of a copy, is not conveying.
@ -204,7 +188,63 @@ appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code; non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with t recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the copy of the Corresponding Source for all the software in the
@ -393,7 +433,47 @@ covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients. 10. Automatic Licensing of Downstream Recipients.
E to Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version. propagate the contents of its contributor version.
@ -489,7 +569,63 @@ address new problems or concerns.
Program specifies that a certain numbered version of the GNU Affero General Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered option of following the terms and conditions either of that numbered
version orch source file to most effectively version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
@ -507,7 +643,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU Affero General Public License for more details. GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@ -522,4 +658,4 @@ specific requirements.
You should also get your employer (if you work as a programmer) or school, You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>. <https://www.gnu.org/licenses/>.

View File

@ -86,7 +86,7 @@ class JitConfig extends BaseConfig
$dbvalue = $this->configModel->get($cat, $key); $dbvalue = $this->configModel->get($cat, $key);
if (isset($dbvalue)) { if (isset($dbvalue)) {
$this->configCache->set($cat, $key, $dbvalue); $this->configCache->set($cat, $key, $dbvalue, Cache::SOURCE_DB);
unset($dbvalue); unset($dbvalue);
} }
@ -105,7 +105,7 @@ class JitConfig extends BaseConfig
public function set(string $cat, string $key, $value) public function set(string $cat, string $key, $value)
{ {
// set the cache first // set the cache first
$cached = $this->configCache->set($cat, $key, $value); $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
// If there is no connected adapter, we're finished // If there is no connected adapter, we're finished
if (!$this->configModel->isConnected()) { if (!$this->configModel->isConnected()) {

View File

@ -81,7 +81,7 @@ class PreloadConfig extends BaseConfig
if ($this->configModel->isConnected()) { if ($this->configModel->isConnected()) {
$config = $this->configModel->get($cat, $key); $config = $this->configModel->get($cat, $key);
if (isset($config)) { if (isset($config)) {
$this->configCache->set($cat, $key, $config); $this->configCache->set($cat, $key, $config, Cache::SOURCE_DB);
} }
} }
} }
@ -102,7 +102,7 @@ class PreloadConfig extends BaseConfig
} }
// set the cache first // set the cache first
$cached = $this->configCache->set($cat, $key, $value); $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
// If there is no connected adapter, we're finished // If there is no connected adapter, we're finished
if (!$this->configModel->isConnected()) { if (!$this->configModel->isConnected()) {
@ -133,4 +133,18 @@ class PreloadConfig extends BaseConfig
return $cacheRemoved || $storeRemoved; return $cacheRemoved || $storeRemoved;
} }
public function testSetDouble()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => ['test' => 'it']])
->once();
parent::testSetDouble();
}
} }

View File

@ -133,9 +133,9 @@ class Installer
$returnVal = false; $returnVal = false;
} }
if (!$this->checkHtAccess($baseurl)) { /// @TODO This check should not block installations because of containerization issues
$returnVal = false; /// @see https://github.com/friendica/docker/issues/134
} $this->checkHtAccess($baseurl);
return $returnVal; return $returnVal;
} }

View File

@ -95,8 +95,7 @@ class Invite extends BaseModule
$nmessage = $message; $nmessage = $message;
} }
$additional_headers = 'From: ' . $app->user['email'] . "\n" $additional_headers = 'From: "' . $app->user['email'] . '" <' . DI::emailer()->getSiteEmailAddress() . ">\n"
. 'Sender: ' . DI::emailer()->getSiteEmailAddress() . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit'; . 'Content-transfer-encoding: 8bit';

View File

@ -1330,7 +1330,7 @@ class Transmitter
return $match[0]; return $match[0];
} }
return '[url=' . ($data['alias'] ?: $data['url']) . ']@' . $data['nick'] . '[/url]'; return '[url=' . $data['url'] . ']@' . $data['nick'] . '[/url]';
} }
/** /**

View File

@ -103,6 +103,28 @@ abstract class AbstractLogger implements LoggerInterface
return strtr($message, $replace); return strtr($message, $replace);
} }
/**
* JSON Encodes an complete array including objects with "__toString()" methods
*
* @param array $input an Input Array to encode
*
* @return false|string The json encoded output of the array
*/
protected function jsonEncodeArray(array $input)
{
$output = [];
foreach ($input as $key => $value) {
if (method_exists($value, '__toString')) {
$output[$key] = $value->__toString();
} else {
$output[$key] = $value;
}
}
return @json_encode($output);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -161,8 +161,8 @@ class StreamLogger extends AbstractLogger
$logMessage .= $this->channel . ' '; $logMessage .= $this->channel . ' ';
$logMessage .= '[' . strtoupper($level) . ']: '; $logMessage .= '[' . strtoupper($level) . ']: ';
$logMessage .= $this->psrInterpolate($message, $context) . ' '; $logMessage .= $this->psrInterpolate($message, $context) . ' ';
$logMessage .= @json_encode($context) . ' - '; $logMessage .= $this->jsonEncodeArray($context) . ' - ';
$logMessage .= @json_encode($record); $logMessage .= $this->jsonEncodeArray($record);
$logMessage .= PHP_EOL; $logMessage .= PHP_EOL;
return $logMessage; return $logMessage;

View File

@ -195,8 +195,8 @@ class SyslogLogger extends AbstractLogger
$logMessage .= $this->channel . ' '; $logMessage .= $this->channel . ' ';
$logMessage .= '[' . $this->logToString[$level] . ']: '; $logMessage .= '[' . $this->logToString[$level] . ']: ';
$logMessage .= $this->psrInterpolate($message, $context) . ' '; $logMessage .= $this->psrInterpolate($message, $context) . ' ';
$logMessage .= @json_encode($context) . ' - '; $logMessage .= $this->jsonEncodeArray($context) . ' - ';
$logMessage .= @json_encode($record); $logMessage .= $this->jsonEncodeArray($record);
return $logMessage; return $logMessage;
} }

View File

@ -512,7 +512,6 @@ class ParseUrl
{ {
if (!empty($siteinfo['images'])) { if (!empty($siteinfo['images'])) {
array_walk($siteinfo['images'], function (&$image) use ($page_url) { array_walk($siteinfo['images'], function (&$image) use ($page_url) {
$image = [];
// According to the specifications someone could place a picture url into the content field as well. // According to the specifications someone could place a picture url into the content field as well.
// But this doesn't seem to happen in the wild, so we don't cover it here. // But this doesn't seem to happen in the wild, so we don't cover it here.
if (!empty($image['url'])) { if (!empty($image['url'])) {
@ -525,7 +524,11 @@ class ParseUrl
$image['contenttype'] = $photodata['mime']; $image['contenttype'] = $photodata['mime'];
unset($image['url']); unset($image['url']);
ksort($image); ksort($image);
} else {
$image = [];
} }
} else {
$image = [];
} }
}); });
@ -711,7 +714,7 @@ class ParseUrl
array_walk_recursive($siteinfo, function (&$element) { array_walk_recursive($siteinfo, function (&$element) {
if (is_string($element)) { if (is_string($element)) {
$element = html_entity_decode($element, ENT_COMPAT, 'UTF-8'); $element = trim(strip_tags(html_entity_decode($element, ENT_COMPAT, 'UTF-8')));
} }
}); });

View File

@ -319,4 +319,27 @@ class CacheTest extends MockedTest
self::assertEquals(23, $configCache->get('database', 'password')); self::assertEquals(23, $configCache->get('database', 'password'));
self::assertEmpty($configCache->get('database', 'username')); self::assertEmpty($configCache->get('database', 'username'));
} }
/**
* Test the set() method with overrides
* @dataProvider dataTests
*/
public function testSetOverrides($data)
{
$configCache = new Cache();
$configCache->load($data, Cache::SOURCE_DB);
// test with wrong override
self::assertFalse($configCache->set('system', 'test', '1234567', Cache::SOURCE_FILE));
self::assertEquals($data['system']['test'], $configCache->get('system', 'test'));
// test with override (equal)
self::assertTrue($configCache->set('system', 'test', '8910', Cache::SOURCE_DB));
self::assertEquals('8910', $configCache->get('system', 'test'));
// test with override (over)
self::assertTrue($configCache->set('system', 'test', '111213', Cache::SOURCE_ENV));
self::assertEquals('111213', $configCache->get('system', 'test'));
}
} }

View File

@ -437,4 +437,35 @@ abstract class ConfigTest extends MockedTest
self::assertEmpty($this->testedConfig->getCache()->getAll()); self::assertEmpty($this->testedConfig->getCache()->getAll());
} }
/**
* Test the configuration get() and set() method where the db value has a higher prio than the config file
*/
public function testSetGetHighPrio()
{
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
$this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE);
self::assertEquals('prio', $this->testedConfig->get('config', 'test'));
// now you have to get the new variable entry because of the new set the get refresh succeed as well
self::assertTrue($this->testedConfig->set('config', 'test', '123'));
self::assertEquals('123', $this->testedConfig->get('config', 'test', '', true));
}
/**
* Test the configuration get() and set() method where the db value has a lower prio than the env
*/
public function testSetGetLowPrio()
{
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
self::assertEquals('it', $this->testedConfig->get('config', 'test'));
$this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_ENV);
// now you have to get the env variable entry as output, even with a new set (which failed) and a get refresh
self::assertFalse($this->testedConfig->set('config', 'test', '123'));
self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true));
}
} }

View File

@ -198,4 +198,58 @@ class JitConfigTest extends ConfigTest
parent::testDeleteWithDB(); parent::testDeleteWithDB();
} }
public function testSetGetHighPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => []])
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('prio')
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('123')
->once();
parent::testSetGetHighPrio();
}
public function testSetGetLowPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => ['test' => 'it']])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('it')
->once();
parent::testSetGetLowPrio();
}
} }

View File

@ -162,4 +162,52 @@ class PreloadConfigTest extends ConfigTest
parent::testDeleteWithDB(); parent::testDeleteWithDB();
} }
public function testSetGetHighPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => []])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('123')
->once();
parent::testSetGetHighPrio();
}
public function testSetGetLowPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => ['test' => 'it']])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('it')
->once();
parent::testSetGetLowPrio();
}
} }

View File

@ -159,4 +159,23 @@ abstract class AbstractLoggerTest extends MockedTest
self::assertContains(@json_encode($context), $text); self::assertContains(@json_encode($context), $text);
} }
/**
* Test a message with an exception
*/
public function testExceptionHandling()
{
$e = new \Exception("Test String", 123);
$eFollowUp = new \Exception("FollowUp", 456, $e);
$assertion = $eFollowUp->__toString();
$logger = $this->getInstance();
$logger->alert('test', ['e' => $eFollowUp]);
$text = $this->getContent();
self::assertLogline($text);
self::assertContains(@json_encode($assertion), $this->getContent());
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff