Merge branch 'develop' of https://github.com/friendica/friendica into develop

This commit is contained in:
Ralf Thees 2018-10-23 15:52:29 +02:00
commit 5583c070e0
14 changed files with 102 additions and 28 deletions

View file

@ -149,7 +149,7 @@ As Friendica is using a [Twitter/GNU Social compatible API](help/api) any of the
Furthermore there are several client projects, especially for use with Friendica. Furthermore there are several client projects, especially for use with Friendica.
If you are interested in improving those clients, please contact the developers of the clients directly. If you are interested in improving those clients, please contact the developers of the clients directly.
* Android / LinageOS: **Friendiqa** [src](https://github.com/LubuWest/Friendiqa) developed by [Marco R](https://freunde.ma-nic.de/profile/marco) * Android / LinageOS: **Friendiqa** [src](https://git.friendi.ca/lubuwest/Friendiqa)/[Google Play](https://play.google.com/store/apps/details?id=org.qtproject.friendiqa) developed by [Marco R](https://freunde.ma-nic.de/profile/marco)
* iOS: *currently no client* * iOS: *currently no client*
* SailfishOS: **Friendiy** [src](https://kirgroup.com/projects/fabrixxm/harbour-friendly) - developed by [Fabio](https://kirgroup.com/profile/fabrixxm/?tab=profile) * SailfishOS: **Friendiy** [src](https://kirgroup.com/projects/fabrixxm/harbour-friendly) - developed by [Fabio](https://kirgroup.com/profile/fabrixxm/?tab=profile)
* Windows: **Friendica Mobile** for Windows versions [before 8.1](http://windowsphone.com/s?appid=e3257730-c9cf-4935-9620-5261e3505c67) and [Windows 10](https://www.microsoft.com/store/apps/9nblggh0fhmn) - developed by [Gerhard Seeber](http://mozartweg.dyndns.org/friendica/profile/gerhard/?tab=profile) * Windows: **Friendica Mobile** for Windows versions [before 8.1](http://windowsphone.com/s?appid=e3257730-c9cf-4935-9620-5261e3505c67) and [Windows 10](https://www.microsoft.com/store/apps/9nblggh0fhmn) - developed by [Gerhard Seeber](http://mozartweg.dyndns.org/friendica/profile/gerhard/?tab=profile)

View file

@ -549,14 +549,14 @@ function dfrn_poll_content(App $a)
switch ($destination_url) { switch ($destination_url) {
case 'profile': case 'profile':
$a->internalRedirect('profile/' . $profile . '?f=&tab=profile'; $a->internalRedirect('profile/' . $profile . '?f=&tab=profile');
break; break;
case 'photos': case 'photos':
$a->internalRedirect('photos/' . $profile; $a->internalRedirect('photos/' . $profile);
break; break;
case 'status': case 'status':
case '': case '':
$a->internalRedirect('profile/' . $profile; $a->internalRedirect('profile/' . $profile);
break; break;
default: default:
$appendix = (strstr($destination_url, '?') ? '&f=&redir=1' : '?f=&redir=1'); $appendix = (strstr($destination_url, '?') ? '&f=&redir=1' : '?f=&redir=1');

View file

@ -17,5 +17,5 @@ function toggle_mobile_init(App $a) {
$address = ''; $address = '';
} }
$a->internalRedirect($address); System::externalRedirect($address);
} }

View file

@ -1772,7 +1772,7 @@ class App
} }
$privateapps = Core\Config::get('config', 'private_addons', false); $privateapps = Core\Config::get('config', 'private_addons', false);
if (is_array($this->addons) && in_array($this->module, $this->addons) && file_exists("addon/{$this->module}/{$this->module}.php")) { if (Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
//Check if module is an app and if public access to apps is allowed or not //Check if module is an app and if public access to apps is allowed or not
if ((!local_user()) && Core\Addon::isApp($this->module) && $privateapps) { if ((!local_user()) && Core\Addon::isApp($this->module) && $privateapps) {
info(Core\L10n::t("You must be logged in to use addons. ")); info(Core\L10n::t("You must be logged in to use addons. "));
@ -2000,7 +2000,7 @@ class App
public function internalRedirect($toUrl = '', $ssl = false) public function internalRedirect($toUrl = '', $ssl = false)
{ {
if (filter_var($toUrl, FILTER_VALIDATE_URL)) { if (filter_var($toUrl, FILTER_VALIDATE_URL)) {
throw new InternalServerErrorException('URL is not a relative path, please use System::externalRedirectTo'); throw new InternalServerErrorException("'$toUrl is not a relative path, please use System::externalRedirectTo");
} }
$redirectTo = $this->getBaseURL($ssl) . '/' . ltrim($toUrl, '/'); $redirectTo = $this->getBaseURL($ssl) . '/' . ltrim($toUrl, '/');

View file

@ -97,6 +97,7 @@ class Install
* - Creates `config/local.ini.php` * - Creates `config/local.ini.php`
* - Installs Database Structure * - Installs Database Structure
* *
* @param string $phppath Path to the PHP-Binary (optional, if not set e.g. 'php' or '/usr/bin/php')
* @param string $urlpath Path based on the URL of Friendica (e.g. '/friendica') * @param string $urlpath Path based on the URL of Friendica (e.g. '/friendica')
* @param string $dbhost Hostname/IP of the Friendica Database * @param string $dbhost Hostname/IP of the Friendica Database
* @param string $dbuser Username of the Database connection credentials * @param string $dbuser Username of the Database connection credentials
@ -106,7 +107,6 @@ class Install
* @param string $language 2-letter ISO 639-1 code (eg. 'en') * @param string $language 2-letter ISO 639-1 code (eg. 'en')
* @param string $adminmail Mail-Adress of the administrator * @param string $adminmail Mail-Adress of the administrator
* @param string $basepath The basepath of Friendica * @param string $basepath The basepath of Friendica
* @param string $phpath Path to the PHP-Binary (optional, if not set e.g. 'php' or '/usr/bin/php')
* *
* @return bool|string true if the config was created, the text if something went wrong * @return bool|string true if the config was created, the text if something went wrong
*/ */

View file

@ -247,7 +247,7 @@ class System extends BaseObject
public static function externalRedirect($url) public static function externalRedirect($url)
{ {
if (!filter_var($url, FILTER_VALIDATE_URL)) { if (!filter_var($url, FILTER_VALIDATE_URL)) {
throw new InternalServerErrorException('URL is not a fully qualified URL, please use App->internalRedirect() instead'); throw new InternalServerErrorException("'$url' is not a fully qualified URL, please use App->internalRedirect() instead");
} }
header("Location: $url"); header("Location: $url");

View file

@ -243,7 +243,9 @@ class Worker
self::execFunction($queue, $include, $argv, true); self::execFunction($queue, $include, $argv, true);
$stamp = (float)microtime(true); $stamp = (float)microtime(true);
if (DBA::update('workerqueue', ['done' => true], ['id' => $queue['id']])) {
$condition = ["`id` = ? AND `next_try` < ?", $queue['id'], DateTimeFormat::utcNow()];
if (DBA::update('workerqueue', ['done' => true], $condition)) {
Config::set('system', 'last_worker_execution', DateTimeFormat::utcNow()); Config::set('system', 'last_worker_execution', DateTimeFormat::utcNow());
} }
self::$db_duration = (microtime(true) - $stamp); self::$db_duration = (microtime(true) - $stamp);
@ -1137,8 +1139,8 @@ class Worker
$id = $queue['id']; $id = $queue['id'];
if ($retrial > 14) { if ($retrial > 14) {
logger('Id ' . $id . ' had been tried 14 times, it will be deleted now.', LOGGER_DEBUG); logger('Id ' . $id . ' had been tried 14 times. We stop now.', LOGGER_DEBUG);
DBA::delete('workerqueue', ['id' => $id]); return;
} }
// Calculate the delay until the next trial // Calculate the delay until the next trial

View file

@ -936,6 +936,8 @@ class Transmitter
* @param integer $uid User ID * @param integer $uid User ID
* @param string $inbox Target inbox * @param string $inbox Target inbox
* @param integer $suggestion_id Suggestion ID * @param integer $suggestion_id Suggestion ID
*
* @return boolean was the transmission successful?
*/ */
public static function sendContactSuggestion($uid, $inbox, $suggestion_id) public static function sendContactSuggestion($uid, $inbox, $suggestion_id)
{ {
@ -957,7 +959,7 @@ class Transmitter
$signed = LDSignature::sign($data, $owner); $signed = LDSignature::sign($data, $owner);
logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG); logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
HTTPSignature::transmit($signed, $inbox, $uid); return HTTPSignature::transmit($signed, $inbox, $uid);
} }
/** /**
@ -965,6 +967,8 @@ class Transmitter
* *
* @param integer $uid User ID * @param integer $uid User ID
* @param string $inbox Target inbox * @param string $inbox Target inbox
*
* @return boolean was the transmission successful?
*/ */
public static function sendProfileDeletion($uid, $inbox) public static function sendProfileDeletion($uid, $inbox)
{ {
@ -984,7 +988,7 @@ class Transmitter
$signed = LDSignature::sign($data, $owner); $signed = LDSignature::sign($data, $owner);
logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG); logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
HTTPSignature::transmit($signed, $inbox, $uid); return HTTPSignature::transmit($signed, $inbox, $uid);
} }
/** /**
@ -992,6 +996,8 @@ class Transmitter
* *
* @param integer $uid User ID * @param integer $uid User ID
* @param string $inbox Target inbox * @param string $inbox Target inbox
*
* @return boolean was the transmission successful?
*/ */
public static function sendProfileUpdate($uid, $inbox) public static function sendProfileUpdate($uid, $inbox)
{ {
@ -1011,7 +1017,7 @@ class Transmitter
$signed = LDSignature::sign($data, $owner); $signed = LDSignature::sign($data, $owner);
logger('Deliver profile update for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG); logger('Deliver profile update for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
HTTPSignature::transmit($signed, $inbox, $uid); return HTTPSignature::transmit($signed, $inbox, $uid);
} }
/** /**

View file

@ -272,9 +272,11 @@ class HTTPSignature
/** /**
* @brief Transmit given data to a target for a user * @brief Transmit given data to a target for a user
* *
* @param $data * @param array $data Data that is about to be send
* @param $target * @param string $target The URL of the inbox
* @param $uid * @param integer $uid User id of the sender
*
* @return boolean Was the transmission successful?
*/ */
public static function transmit($data, $target, $uid) public static function transmit($data, $target, $uid)
{ {
@ -303,8 +305,11 @@ class HTTPSignature
$headers[] = 'Content-Type: application/activity+json'; $headers[] = 'Content-Type: application/activity+json';
$postResult = Network::post($target, $content, $headers); $postResult = Network::post($target, $content, $headers);
$return_code = $postResult->getReturnCode();
logger('Transmit to ' . $target . ' returned ' . $postResult->getReturnCode()); logger('Transmit to ' . $target . ' returned ' . $return_code);
return ($return_code >= 200) && ($return_code <= 299);
} }
/** /**

View file

@ -7,6 +7,7 @@ namespace Friendica\Worker;
use Friendica\BaseObject; use Friendica\BaseObject;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Core\Worker;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
class APDelivery extends BaseObject class APDelivery extends BaseObject
@ -23,19 +24,25 @@ class APDelivery extends BaseObject
{ {
logger('Invoked: ' . $cmd . ': ' . $item_id . ' to ' . $inbox, LOGGER_DEBUG); logger('Invoked: ' . $cmd . ': ' . $item_id . ' to ' . $inbox, LOGGER_DEBUG);
$success = true;
if ($cmd == Delivery::MAIL) { if ($cmd == Delivery::MAIL) {
} elseif ($cmd == Delivery::SUGGESTION) { } elseif ($cmd == Delivery::SUGGESTION) {
ActivityPub\Transmitter::sendContactSuggestion($uid, $inbox, $item_id); $success = ActivityPub\Transmitter::sendContactSuggestion($uid, $inbox, $item_id);
} elseif ($cmd == Delivery::RELOCATION) { } elseif ($cmd == Delivery::RELOCATION) {
} elseif ($cmd == Delivery::REMOVAL) { } elseif ($cmd == Delivery::REMOVAL) {
ActivityPub\Transmitter::sendProfileDeletion($uid, $inbox); $success = ActivityPub\Transmitter::sendProfileDeletion($uid, $inbox);
} elseif ($cmd == Delivery::PROFILEUPDATE) { } elseif ($cmd == Delivery::PROFILEUPDATE) {
ActivityPub\Transmitter::sendProfileUpdate($uid, $inbox); $success = ActivityPub\Transmitter::sendProfileUpdate($uid, $inbox);
} else { } else {
$data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id); $data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id);
if (!empty($data)) { if (!empty($data)) {
HTTPSignature::transmit($data, $inbox, $uid); $success = HTTPSignature::transmit($data, $inbox, $uid);
} }
} }
if (!$success) {
Worker::defer();
}
} }
} }

View file

@ -54,6 +54,7 @@ class Delivery extends BaseObject
$uid = $target_item['uid']; $uid = $target_item['uid'];
} elseif ($cmd == self::RELOCATION) { } elseif ($cmd == self::RELOCATION) {
$uid = $item_id; $uid = $item_id;
$target_item = [];
} else { } else {
$item = Item::selectFirst(['parent'], ['id' => $item_id]); $item = Item::selectFirst(['parent'], ['id' => $item_id]);
if (!DBA::isResult($item) || empty($item['parent'])) { if (!DBA::isResult($item) || empty($item['parent'])) {

View file

@ -193,10 +193,10 @@ CONF;
$this->assertConfig('database', 'database', $this->db_data); $this->assertConfig('database', 'database', $this->db_data);
$this->assertConfig('config', 'admin_email', 'admin@friendica.local'); $this->assertConfig('config', 'admin_email', 'admin@friendica.local');
$this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); $this->assertConfig('system', 'default_timezone', 'Europe/Berlin');
$this->assertConfig('system', 'language', 'de'); // TODO language changes back to en
//$this->assertConfig('system', 'language', 'de');
} }
/** /**
* @medium * @medium
*/ */
@ -218,8 +218,9 @@ CONF;
$this->assertConfig('database', 'database', ''); $this->assertConfig('database', 'database', '');
$this->assertConfig('config', 'admin_email', 'admin@friendica.local'); $this->assertConfig('config', 'admin_email', 'admin@friendica.local');
$this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); $this->assertConfig('system', 'default_timezone', 'Europe/Berlin');
$this->assertConfig('system', 'language', 'de');
$this->assertConfig('system', 'urlpath', '/friendica'); $this->assertConfig('system', 'urlpath', '/friendica');
// TODO language changes back to en
//$this->assertConfig('system', 'language', 'de');
} }
/** /**
@ -264,8 +265,9 @@ CONF;
$this->assertConfig('database', 'database', $this->db_data); $this->assertConfig('database', 'database', $this->db_data);
$this->assertConfig('config', 'admin_email', 'admin@friendica.local'); $this->assertConfig('config', 'admin_email', 'admin@friendica.local');
$this->assertConfig('system', 'default_timezone', 'Europe/Berlin'); $this->assertConfig('system', 'default_timezone', 'Europe/Berlin');
$this->assertConfig('system', 'language', 'de');
$this->assertConfig('system', 'urlpath', '/friendica'); $this->assertConfig('system', 'urlpath', '/friendica');
// TODO language changes back to en
//$this->assertConfig('system', 'language', 'de');
} }
/** /**

View file

@ -50,6 +50,24 @@ class InstallTest extends TestCase
}; };
} }
/**
* Replaces class_exist results with given mocks
*
* @param array $classes a list from class names and their results
*/
private function setClasses($classes)
{
global $phpMock;
$phpMock['class_exists'] = function($class) use ($classes) {
foreach ($classes as $name => $value) {
if ($class == $name) {
return $value;
}
}
return '__phpunit_continue__';
};
}
/** /**
* @small * @small
*/ */
@ -248,10 +266,13 @@ class InstallTest extends TestCase
->shouldReceive('supportedTypes') ->shouldReceive('supportedTypes')
->andReturn(['image/gif' => 'gif']); ->andReturn(['image/gif' => 'gif']);
$this->setClasses(['Imagick' => true]);
$install = new Install(); $install = new Install();
// even there is no supported type, Imagick should return true (because it is not required) // even there is no supported type, Imagick should return true (because it is not required)
$this->assertTrue($install->checkImagick()); $this->assertTrue($install->checkImagick());
$this->assertCheckExist(1, $this->assertCheckExist(1,
L10n::t('ImageMagick supports GIF'), L10n::t('ImageMagick supports GIF'),
'', '',
@ -270,6 +291,8 @@ class InstallTest extends TestCase
->shouldReceive('supportedTypes') ->shouldReceive('supportedTypes')
->andReturn([]); ->andReturn([]);
$this->setClasses(['Imagick' => true]);
$install = new Install(); $install = new Install();
// even there is no supported type, Imagick should return true (because it is not required) // even there is no supported type, Imagick should return true (because it is not required)
@ -281,6 +304,22 @@ class InstallTest extends TestCase
false, false,
$install->getChecks()); $install->getChecks());
} }
public function testImagickNotInstalled()
{
$this->setClasses(['Imagick' => false]);
$install = new Install();
// even there is no supported type, Imagick should return true (because it is not required)
$this->assertTrue($install->checkImagick());
$this->assertCheckExist(0,
L10n::t('ImageMagick PHP extension is not installed'),
'',
false,
false,
$install->getChecks());
}
} }
/** /**
@ -301,3 +340,15 @@ function function_exists($function_name)
} }
return call_user_func_array('\function_exists', func_get_args()); return call_user_func_array('\function_exists', func_get_args());
} }
function class_exists($class_name)
{
global $phpMock;
if (isset($phpMock['class_exists'])) {
$result = call_user_func_array($phpMock['class_exists'], func_get_args());
if ($result !== '__phpunit_continue__') {
return $result;
}
}
return call_user_func_array('\class_exists', func_get_args());
}

View file

@ -34,4 +34,4 @@ class SystemTest extends TestCase
$guid = System::createGUID(23, 'test'); $guid = System::createGUID(23, 'test');
$this->assertGuid($guid, 23, 'test'); $this->assertGuid($guid, 23, 'test');
} }
} }