2017-05-08 06:11:38 +00:00
< ? php
2018-01-22 14:54:13 +00:00
/**
2023-01-01 14:36:24 +00:00
* @ copyright Copyright ( C ) 2010 - 2023 , the Friendica project
2020-02-09 15:18:46 +00:00
*
* @ license GNU AGPL version 3 or any later version
*
* 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 < https :// www . gnu . org / licenses />.
*
2018-01-22 14:54:13 +00:00
*/
2020-02-09 15:18:46 +00:00
2017-05-08 06:11:38 +00:00
namespace Friendica ;
2018-07-20 02:15:21 +00:00
use Exception ;
2019-08-12 16:13:58 +00:00
use Friendica\App\Arguments ;
2019-08-15 15:23:00 +00:00
use Friendica\App\BaseURL ;
2021-11-21 22:37:17 +00:00
use Friendica\Capabilities\ICanCreateResponses ;
2023-01-08 06:17:06 +00:00
use Friendica\Content\Nav ;
2021-10-26 19:44:29 +00:00
use Friendica\Core\Config\Factory\Config ;
2022-10-20 19:27:32 +00:00
use Friendica\Core\Session\Capability\IHandleUserSessions ;
2022-12-16 20:59:32 +00:00
use Friendica\Database\Definition\DbaDefinition ;
use Friendica\Database\Definition\ViewDefinition ;
2021-03-10 14:40:42 +00:00
use Friendica\Module\Maintenance ;
2020-09-30 14:53:18 +00:00
use Friendica\Security\Authentication ;
2021-10-26 19:44:29 +00:00
use Friendica\Core\Config\ValueObject\Cache ;
use Friendica\Core\Config\Capability\IManageConfigValues ;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues ;
2020-01-18 19:59:39 +00:00
use Friendica\Core\L10n ;
2019-07-24 00:01:45 +00:00
use Friendica\Core\System ;
2019-04-01 01:50:00 +00:00
use Friendica\Core\Theme ;
2019-06-06 22:10:45 +00:00
use Friendica\Database\Database ;
2021-05-23 10:39:11 +00:00
use Friendica\Model\Contact ;
2019-03-19 06:44:51 +00:00
use Friendica\Model\Profile ;
2019-08-12 16:13:58 +00:00
use Friendica\Module\Special\HTTPException as ModuleHTTPException ;
2019-05-02 01:33:33 +00:00
use Friendica\Network\HTTPException ;
2021-10-03 16:38:47 +00:00
use Friendica\Util\DateTimeFormat ;
2021-11-28 12:44:42 +00:00
use Friendica\Util\HTTPInputData ;
2019-03-19 06:44:51 +00:00
use Friendica\Util\HTTPSignature ;
2019-02-16 22:11:30 +00:00
use Friendica\Util\Profiler ;
2019-04-01 01:50:00 +00:00
use Friendica\Util\Strings ;
2018-12-30 20:42:56 +00:00
use Psr\Log\LoggerInterface ;
2017-05-11 15:53:04 +00:00
2017-05-08 06:11:38 +00:00
/**
2020-01-19 06:05:23 +00:00
* Our main application structure for the life of this page .
2017-05-08 06:11:38 +00:00
*
* Primarily deals with the URL that got us here
* and tries to make some sense of it , and
* stores our page contents and config storage
* and anything else that might need to be passed around
* before we spit the page out .
*
*/
2018-01-16 00:13:21 +00:00
class App
{
2022-10-17 10:37:48 +00:00
const PLATFORM = 'Friendica' ;
const CODENAME = 'Giant Rhubarb' ;
2023-10-04 18:40:08 +00:00
const VERSION = '2023.09-rc' ;
2022-10-17 10:37:48 +00:00
2017-05-08 06:11:38 +00:00
// Allow themes to control internal parameters
// by changing App values in theme.php
2021-07-25 19:39:10 +00:00
private $theme_info = [
2021-07-25 19:07:03 +00:00
'videowidth' => 425 ,
'videoheight' => 350 ,
];
2018-09-21 01:01:05 +00:00
2021-07-24 22:08:33 +00:00
private $timezone = '' ;
2021-07-24 20:51:55 +00:00
private $profile_owner = 0 ;
private $contact_id = 0 ;
2021-07-24 22:08:33 +00:00
private $queue = [];
2021-07-24 20:42:09 +00:00
2018-10-06 14:27:20 +00:00
/**
* @ var App\Mode The Mode of the Application
*/
private $mode ;
2018-10-09 17:58:58 +00:00
/**
2019-04-08 19:12:10 +00:00
* @ var BaseURL
2018-10-09 17:58:58 +00:00
*/
2019-04-08 19:12:10 +00:00
private $baseURL ;
2018-10-09 17:58:58 +00:00
2019-10-06 16:07:06 +00:00
/** @var string The name of the current theme */
2018-10-09 17:58:58 +00:00
private $currentTheme ;
2019-10-06 16:07:06 +00:00
/** @var string The name of the current mobile theme */
private $currentMobileTheme ;
2018-10-09 17:58:58 +00:00
2018-12-30 20:42:56 +00:00
/**
2021-10-26 19:44:29 +00:00
* @ var IManageConfigValues The config
2019-02-03 21:22:04 +00:00
*/
private $config ;
2019-02-17 20:12:12 +00:00
/**
* @ var LoggerInterface The logger
2018-12-30 20:42:56 +00:00
*/
private $logger ;
2019-02-03 21:22:04 +00:00
/**
2019-02-16 22:11:30 +00:00
* @ var Profiler The profiler of this app
2019-02-03 21:22:04 +00:00
*/
2019-02-16 22:11:30 +00:00
private $profiler ;
2019-02-03 21:22:04 +00:00
2019-06-06 22:10:45 +00:00
/**
* @ var Database The Friendica database connection
*/
private $database ;
2019-07-09 19:44:02 +00:00
/**
* @ var L10n The translator
*/
private $l10n ;
2019-08-12 16:13:58 +00:00
/**
* @ var App\Arguments
*/
private $args ;
2020-01-18 15:50:57 +00:00
/**
2021-10-26 19:44:29 +00:00
* @ var IManagePersonalConfigValues
2020-01-18 15:50:57 +00:00
*/
private $pConfig ;
2022-10-20 20:06:25 +00:00
/**
* @ var IHandleUserSessions
*/
2022-10-23 18:41:17 +00:00
private $session ;
2022-10-20 20:06:25 +00:00
2021-08-08 10:14:56 +00:00
/**
2022-12-26 12:08:41 +00:00
* @ deprecated 2022.03
* @ see IHandleUserSessions :: isAuthenticated ()
2021-08-08 10:14:56 +00:00
*/
2022-06-16 14:25:30 +00:00
public function isLoggedIn () : bool
2021-08-08 19:30:21 +00:00
{
2022-12-26 12:08:41 +00:00
return $this -> session -> isAuthenticated ();
2021-08-08 19:30:21 +00:00
}
2021-11-04 20:29:59 +00:00
/**
2022-12-26 12:08:41 +00:00
* @ deprecated 2022.03
* @ see IHandleUserSessions :: isSiteAdmin ()
2021-11-04 20:29:59 +00:00
*/
2022-06-16 14:25:30 +00:00
public function isSiteAdmin () : bool
2021-11-04 20:29:59 +00:00
{
2022-12-26 12:08:41 +00:00
return $this -> session -> isSiteAdmin ();
2021-11-04 20:29:59 +00:00
}
2021-08-08 10:14:56 +00:00
/**
2022-12-26 12:08:41 +00:00
* @ deprecated 2022.03
* @ see IHandleUserSessions :: getLocalUserId ()
2021-08-08 10:14:56 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getLoggedInUserId () : int
2021-08-08 10:14:56 +00:00
{
2022-12-26 12:08:41 +00:00
return $this -> session -> getLocalUserId ();
2021-08-08 10:14:56 +00:00
}
/**
2022-12-26 12:08:41 +00:00
* @ deprecated 2022.03
* @ see IHandleUserSessions :: getLocalUserNickname ()
2021-08-08 10:14:56 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getLoggedInUserNickname () : string
2021-08-08 10:14:56 +00:00
{
2022-12-26 12:08:41 +00:00
return $this -> session -> getLocalUserNickname ();
2021-08-08 10:14:56 +00:00
}
2021-07-24 20:42:09 +00:00
/**
* Set the profile owner ID
*
2021-07-24 22:08:33 +00:00
* @ param int $owner_id
* @ return void
2021-07-24 20:42:09 +00:00
*/
2021-07-24 20:34:07 +00:00
public function setProfileOwner ( int $owner_id )
{
$this -> profile_owner = $owner_id ;
}
2021-07-24 20:42:09 +00:00
/**
* Get the profile owner ID
*
2021-07-24 22:08:33 +00:00
* @ return int
2021-07-24 20:42:09 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getProfileOwner () : int
2021-07-24 20:34:07 +00:00
{
return $this -> profile_owner ;
}
2021-07-24 20:42:09 +00:00
/**
* Set the contact ID
2021-07-24 22:08:33 +00:00
*
* @ param int $contact_id
* @ return void
2021-07-24 20:42:09 +00:00
*/
2021-07-24 20:34:07 +00:00
public function setContactId ( int $contact_id )
{
$this -> contact_id = $contact_id ;
}
2021-07-24 20:42:09 +00:00
/**
* Get the contact ID
*
2021-07-24 22:08:33 +00:00
* @ return int
2021-07-24 20:42:09 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getContactId () : int
2021-07-24 20:34:07 +00:00
{
return $this -> contact_id ;
}
2021-07-24 21:16:53 +00:00
/**
* Set the timezone
2021-07-24 22:08:33 +00:00
*
2021-10-03 16:38:47 +00:00
* @ param string $timezone A valid time zone identifier , see https :// www . php . net / manual / en / timezones . php
2021-07-24 22:08:33 +00:00
* @ return void
2021-07-24 21:16:53 +00:00
*/
public function setTimeZone ( string $timezone )
{
2021-10-03 16:38:47 +00:00
$this -> timezone = ( new \DateTimeZone ( $timezone )) -> getName ();
DateTimeFormat :: setLocalTimeZone ( $this -> timezone );
2021-07-24 21:16:53 +00:00
}
/**
* Get the timezone
*
2021-07-24 22:08:33 +00:00
* @ return int
2021-07-24 21:16:53 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getTimeZone () : string
2021-07-24 21:16:53 +00:00
{
return $this -> timezone ;
}
2021-07-25 19:39:10 +00:00
/**
* Set workerqueue information
*
2022-11-12 17:01:22 +00:00
* @ param array $queue
* @ return void
2021-07-25 19:39:10 +00:00
*/
2021-07-24 22:08:33 +00:00
public function setQueue ( array $queue )
{
$this -> queue = $queue ;
}
2021-07-25 19:39:10 +00:00
/**
* Fetch workerqueue information
*
2022-06-16 14:25:30 +00:00
* @ return array Worker queue
2021-07-25 19:39:10 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getQueue () : array
2021-07-24 22:08:33 +00:00
{
return $this -> queue ? ? [];
}
2021-07-25 19:39:10 +00:00
/**
* Fetch a specific workerqueue field
*
2022-06-16 14:25:30 +00:00
* @ param string $index Work queue record to fetch
* @ return mixed Work queue item or NULL if not found
2021-07-25 19:39:10 +00:00
*/
2021-07-24 22:08:33 +00:00
public function getQueueValue ( string $index )
{
return $this -> queue [ $index ] ? ? null ;
}
2021-07-25 19:39:10 +00:00
public function setThemeInfoValue ( string $index , $value )
{
$this -> theme_info [ $index ] = $value ;
}
public function getThemeInfo ()
{
return $this -> theme_info ;
}
public function getThemeInfoValue ( string $index , $default = null )
{
return $this -> theme_info [ $index ] ? ? $default ;
}
2019-02-03 21:22:04 +00:00
/**
* Returns the current config cache of this node
*
2020-01-19 21:23:44 +00:00
* @ return Cache
2019-02-03 21:22:04 +00:00
*/
2019-02-10 18:52:21 +00:00
public function getConfigCache ()
2019-02-03 21:22:04 +00:00
{
2019-02-10 18:52:21 +00:00
return $this -> config -> getCache ();
2019-02-03 21:22:04 +00:00
}
/**
* The basepath of this app
*
2022-06-16 14:25:30 +00:00
* @ return string Base path from configuration
2019-02-03 21:22:04 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getBasePath () : string
2019-02-03 21:22:04 +00:00
{
2022-12-28 01:07:38 +00:00
return $this -> config -> get ( 'system' , 'basepath' );
2019-02-03 21:22:04 +00:00
}
2017-05-08 06:11:38 +00:00
/**
2021-10-26 20:09:11 +00:00
* @ param Database $database The Friendica Database
* @ param IManageConfigValues $config The Configuration
* @ param App\Mode $mode The mode of this Friendica app
* @ param BaseURL $baseURL The full base URL of this Friendica app
* @ param LoggerInterface $logger The current app logger
* @ param Profiler $profiler The profiler of this application
* @ param L10n $l10n The translator instance
* @ param App\Arguments $args The Friendica Arguments of the call
* @ param IManagePersonalConfigValues $pConfig Personal configuration
2022-10-25 06:07:42 +00:00
* @ param IHandleUserSessions $session The ( User ) Session handler
2022-12-16 20:59:32 +00:00
* @ param DbaDefinition $dbaDefinition
* @ param ViewDefinition $viewDefinition
2022-10-23 18:41:17 +00:00
*/
2022-12-16 20:59:32 +00:00
public function __construct ( Database $database , IManageConfigValues $config , App\Mode $mode , BaseURL $baseURL , LoggerInterface $logger , Profiler $profiler , L10n $l10n , Arguments $args , IManagePersonalConfigValues $pConfig , IHandleUserSessions $session , DbaDefinition $dbaDefinition , ViewDefinition $viewDefinition )
2022-10-23 18:41:17 +00:00
{
2022-12-16 20:59:32 +00:00
$this -> database = $database ;
$this -> config = $config ;
$this -> mode = $mode ;
$this -> baseURL = $baseURL ;
$this -> profiler = $profiler ;
$this -> logger = $logger ;
$this -> l10n = $l10n ;
$this -> args = $args ;
$this -> pConfig = $pConfig ;
$this -> session = $session ;
$this -> load ( $dbaDefinition , $viewDefinition );
2019-08-15 14:18:08 +00:00
}
2017-05-08 06:11:38 +00:00
2019-08-15 14:18:08 +00:00
/**
* Load the whole app instance
*/
2022-12-16 20:59:32 +00:00
protected function load ( DbaDefinition $dbaDefinition , ViewDefinition $viewDefinition )
2019-08-15 14:18:08 +00:00
{
2023-05-04 15:48:13 +00:00
if ( $this -> config -> get ( 'system' , 'ini_max_execution_time' ) !== false ) {
set_time_limit (( int ) $this -> config -> get ( 'system' , 'ini_max_execution_time' ));
}
if ( $this -> config -> get ( 'system' , 'ini_pcre_backtrack_limit' ) !== false ) {
ini_set ( 'pcre.backtrack_limit' , ( int ) $this -> config -> get ( 'system' , 'ini_pcre_backtrack_limit' ));
}
2018-07-02 11:23:47 +00:00
2022-10-18 04:35:06 +00:00
// Normally this constant is defined - but not if "pcntl" isn't installed
if ( ! defined ( 'SIGTERM' )) {
define ( 'SIGTERM' , 15 );
}
2021-10-03 16:38:47 +00:00
// Ensure that all "strtotime" operations do run timezone independent
date_default_timezone_set ( 'UTC' );
2017-05-08 06:11:38 +00:00
set_include_path (
get_include_path () . PATH_SEPARATOR
2019-03-23 14:20:51 +00:00
. $this -> getBasePath () . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
. $this -> getBasePath () . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this -> getBasePath ());
2017-05-08 06:11:38 +00:00
2019-08-15 14:18:08 +00:00
$this -> profiler -> reset ();
2018-06-26 00:38:41 +00:00
2019-08-15 14:18:08 +00:00
if ( $this -> mode -> has ( App\Mode :: DBAVAILABLE )) {
2019-02-23 00:24:08 +00:00
Core\Hook :: loadHooks ();
2023-01-05 21:13:10 +00:00
$loader = ( new Config ()) -> createConfigFileManager ( $this -> getBasePath (), $_SERVER );
2019-02-23 00:24:08 +00:00
Core\Hook :: callAll ( 'load_config' , $loader );
2022-12-16 20:59:32 +00:00
// Hooks are now working, reload the whole definitions with hook enabled
$dbaDefinition -> load ( true );
$viewDefinition -> load ( true );
2018-08-27 04:15:55 +00:00
}
$this -> loadDefaultTimezone ();
2019-08-15 14:18:08 +00:00
// Register template engines
Core\Renderer :: registerTemplateEngine ( 'Friendica\Render\FriendicaSmartyEngine' );
2018-08-27 04:15:55 +00:00
}
2018-06-28 03:05:38 +00:00
/**
* Loads the default timezone
*
* Include support for legacy $default_timezone
*
* @ global string $default_timezone
*/
2018-06-26 00:38:41 +00:00
private function loadDefaultTimezone ()
{
2019-02-03 21:22:04 +00:00
if ( $this -> config -> get ( 'system' , 'default_timezone' )) {
2021-10-03 16:38:47 +00:00
$timezone = $this -> config -> get ( 'system' , 'default_timezone' , 'UTC' );
2018-06-26 00:38:41 +00:00
} else {
global $default_timezone ;
2021-10-03 16:38:47 +00:00
$timezone = $default_timezone ? ? '' ? : 'UTC' ;
2018-06-26 00:38:41 +00:00
}
2021-10-03 16:38:47 +00:00
$this -> setTimeZone ( $timezone );
2018-06-26 00:38:41 +00:00
}
2018-04-28 22:30:13 +00:00
/**
2023-03-22 04:07:56 +00:00
* Returns the current theme name . May be overridden by the mobile theme name .
2018-04-28 22:30:13 +00:00
*
2022-06-16 14:25:30 +00:00
* @ return string Current theme name or empty string in installation phase
2019-10-06 16:07:06 +00:00
* @ throws Exception
2018-04-28 22:30:13 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getCurrentTheme () : string
2018-04-28 22:30:13 +00:00
{
2019-08-15 14:18:08 +00:00
if ( $this -> mode -> isInstall ()) {
2018-05-20 05:44:20 +00:00
return '' ;
}
2019-10-06 16:07:06 +00:00
// Specific mobile theme override
2022-10-18 19:10:37 +00:00
if (( $this -> mode -> isMobile () || $this -> mode -> isTablet ()) && $this -> session -> get ( 'show-mobile' , true )) {
2019-10-06 16:07:06 +00:00
$user_mobile_theme = $this -> getCurrentMobileTheme ();
// --- means same mobile theme as desktop
if ( ! empty ( $user_mobile_theme ) && $user_mobile_theme !== '---' ) {
return $user_mobile_theme ;
}
}
2018-12-29 05:18:52 +00:00
if ( ! $this -> currentTheme ) {
$this -> computeCurrentTheme ();
}
2018-04-28 22:30:13 +00:00
2018-10-09 17:58:58 +00:00
return $this -> currentTheme ;
2018-04-28 22:30:13 +00:00
}
2019-10-06 16:07:06 +00:00
/**
* Returns the current mobile theme name .
*
2022-06-16 14:25:30 +00:00
* @ return string Mobile theme name or empty string if installer
2019-10-06 16:07:06 +00:00
* @ throws Exception
*/
2022-06-16 14:25:30 +00:00
public function getCurrentMobileTheme () : string
2019-10-06 16:07:06 +00:00
{
if ( $this -> mode -> isInstall ()) {
return '' ;
}
if ( is_null ( $this -> currentMobileTheme )) {
$this -> computeCurrentMobileTheme ();
}
return $this -> currentMobileTheme ;
}
2022-06-16 14:25:30 +00:00
/**
* Setter for current theme name
*
* @ param string $theme Name of current theme
*/
public function setCurrentTheme ( string $theme )
2018-12-29 05:18:52 +00:00
{
$this -> currentTheme = $theme ;
}
2022-06-16 14:25:30 +00:00
/**
* Setter for current mobile theme name
*
* @ param string $theme Name of current mobile theme
*/
public function setCurrentMobileTheme ( string $theme )
2019-10-06 16:07:06 +00:00
{
$this -> currentMobileTheme = $theme ;
}
2018-04-28 22:30:13 +00:00
/**
2019-10-06 16:07:06 +00:00
* Computes the current theme name based on the node settings , the page owner settings and the user settings
2018-04-28 22:30:13 +00:00
*
* @ throws Exception
*/
private function computeCurrentTheme ()
{
2019-03-23 14:23:23 +00:00
$system_theme = $this -> config -> get ( 'system' , 'theme' );
2018-04-28 22:30:13 +00:00
if ( ! $system_theme ) {
2019-07-09 19:44:02 +00:00
throw new Exception ( $this -> l10n -> t ( 'No system theme config value set.' ));
2018-04-28 22:30:13 +00:00
}
// Sane default
2019-10-06 16:07:06 +00:00
$this -> setCurrentTheme ( $system_theme );
2018-04-28 22:30:13 +00:00
$page_theme = null ;
// Find the theme that belongs to the user whose stuff we are looking at
2022-10-23 18:41:17 +00:00
if ( ! empty ( $this -> profile_owner ) && ( $this -> profile_owner != $this -> session -> getLocalUserId ())) {
2018-04-28 22:30:13 +00:00
// Allow folks to override user themes and always use their own on their own site.
// This works only if the user is on the same server
2021-07-24 10:09:39 +00:00
$user = $this -> database -> selectFirst ( 'user' , [ 'theme' ], [ 'uid' => $this -> profile_owner ]);
2022-10-23 18:41:17 +00:00
if ( $this -> database -> isResult ( $user ) && ! $this -> session -> getLocalUserId ()) {
2018-04-28 22:30:13 +00:00
$page_theme = $user [ 'theme' ];
}
}
2022-10-18 19:10:37 +00:00
$theme_name = $page_theme ? : $this -> session -> get ( 'theme' , $system_theme );
2018-04-28 22:30:13 +00:00
2019-04-01 01:50:00 +00:00
$theme_name = Strings :: sanitizeFilePathItem ( $theme_name );
2018-04-28 22:30:13 +00:00
if ( $theme_name
2019-08-15 14:18:08 +00:00
&& in_array ( $theme_name , Theme :: getAllowedList ())
&& ( file_exists ( 'view/theme/' . $theme_name . '/style.css' )
|| file_exists ( 'view/theme/' . $theme_name . '/style.php' ))
2018-04-28 22:30:13 +00:00
) {
2019-10-06 16:07:06 +00:00
$this -> setCurrentTheme ( $theme_name );
}
}
/**
* Computes the current mobile theme name based on the node settings , the page owner settings and the user settings
*/
private function computeCurrentMobileTheme ()
{
$system_mobile_theme = $this -> config -> get ( 'system' , 'mobile-theme' , '' );
// Sane default
$this -> setCurrentMobileTheme ( $system_mobile_theme );
$page_mobile_theme = null ;
// Find the theme that belongs to the user whose stuff we are looking at
2022-10-23 18:41:17 +00:00
if ( ! empty ( $this -> profile_owner ) && ( $this -> profile_owner != $this -> session -> getLocalUserId ())) {
2019-10-06 16:07:06 +00:00
// Allow folks to override user themes and always use their own on their own site.
// This works only if the user is on the same server
2022-10-23 18:41:17 +00:00
if ( ! $this -> session -> getLocalUserId ()) {
2021-07-24 10:09:39 +00:00
$page_mobile_theme = $this -> pConfig -> get ( $this -> profile_owner , 'system' , 'mobile-theme' );
2019-10-06 16:07:06 +00:00
}
}
2022-10-18 19:10:37 +00:00
$mobile_theme_name = $page_mobile_theme ? : $this -> session -> get ( 'mobile-theme' , $system_mobile_theme );
2019-10-06 16:07:06 +00:00
$mobile_theme_name = Strings :: sanitizeFilePathItem ( $mobile_theme_name );
if ( $mobile_theme_name == '---'
||
in_array ( $mobile_theme_name , Theme :: getAllowedList ())
&& ( file_exists ( 'view/theme/' . $mobile_theme_name . '/style.css' )
|| file_exists ( 'view/theme/' . $mobile_theme_name . '/style.php' ))
) {
$this -> setCurrentMobileTheme ( $mobile_theme_name );
2018-04-28 22:30:13 +00:00
}
}
/**
* Provide a sane default if nothing is chosen or the specified theme does not exist .
*
2023-03-22 04:08:29 +00:00
* @ return string Current theme ' s stylesheet path
2019-10-06 16:07:06 +00:00
* @ throws Exception
2018-04-28 22:30:13 +00:00
*/
2022-06-16 14:25:30 +00:00
public function getCurrentThemeStylesheetPath () : string
2018-04-28 22:30:13 +00:00
{
return Core\Theme :: getStylesheetPath ( $this -> getCurrentTheme ());
}
2018-10-13 16:57:31 +00:00
2018-10-22 02:24:47 +00:00
/**
* Frontend App script
*
* The App object behaves like a container and a dispatcher at the same time , including a representation of the
* request and a representation of the response .
*
* This probably should change to limit the size of this monster method .
2019-08-12 16:13:58 +00:00
*
2021-10-26 19:44:29 +00:00
* @ param App\Router $router
* @ param IManagePersonalConfigValues $pconfig
2021-11-28 13:01:13 +00:00
* @ param Authentication $auth The Authentication backend of the node
* @ param App\Page $page The Friendica page printing container
2022-12-26 20:17:32 +00:00
* @ param ModuleHTTPException $httpException The possible HTTP Exception container
2021-11-28 13:01:13 +00:00
* @ param HTTPInputData $httpInput A library for processing PHP input streams
* @ param float $start_time The start time of the overall script execution
2023-02-18 19:47:52 +00:00
* @ param array $server The $_SERVER array
2020-01-19 21:23:44 +00:00
*
2019-10-06 15:18:51 +00:00
* @ throws HTTPException\InternalServerErrorException
* @ throws \ImagickException
2018-10-22 02:24:47 +00:00
*/
2023-02-18 19:47:52 +00:00
public function runFrontend ( App\Router $router , IManagePersonalConfigValues $pconfig , Authentication $auth , App\Page $page , Nav $nav , ModuleHTTPException $httpException , HTTPInputData $httpInput , float $start_time , array $server )
2018-10-22 02:24:47 +00:00
{
2023-09-11 08:47:35 +00:00
$requeststring = ( $_SERVER [ 'REQUEST_METHOD' ] ? ? '' ) . ' ' . ( $_SERVER [ 'REQUEST_URI' ] ? ? '' ) . ' ' . ( $_SERVER [ 'SERVER_PROTOCOL' ] ? ? '' );
2023-09-11 10:18:02 +00:00
$this -> logger -> debug ( 'Request received' , [ 'address' => $_SERVER [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $_SERVER [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $_SERVER [ 'HTTP_USER_AGENT' ] ? ? '' ]);
2023-09-11 08:47:35 +00:00
2020-12-10 00:02:23 +00:00
$this -> profiler -> set ( $start_time , 'start' );
2020-12-09 22:10:27 +00:00
$this -> profiler -> set ( microtime ( true ), 'classinit' );
2021-11-19 21:47:49 +00:00
$moduleName = $this -> args -> getModuleName ();
2022-09-20 14:30:56 +00:00
$page -> setLogging ( $this -> args -> getMethod (), $this -> args -> getModuleName (), $this -> args -> getCommand ());
2019-08-12 16:13:58 +00:00
2019-07-24 00:01:45 +00:00
try {
// Missing DB connection: ERROR
2019-08-15 14:18:08 +00:00
if ( $this -> mode -> has ( App\Mode :: LOCALCONFIGPRESENT ) && ! $this -> mode -> has ( App\Mode :: DBAVAILABLE )) {
2022-01-03 21:29:26 +00:00
throw new HTTPException\InternalServerErrorException ( $this -> l10n -> t ( 'Apologies but the website is unavailable at the moment.' ));
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-15 14:18:08 +00:00
if ( ! $this -> mode -> isInstall ()) {
2019-07-24 00:01:45 +00:00
// Force SSL redirection
2023-02-18 19:47:52 +00:00
if ( $this -> config -> get ( 'system' , 'force_ssl' ) &&
( empty ( $server [ 'HTTPS' ]) || $server [ 'HTTPS' ] === 'off' ) &&
2023-05-24 12:04:34 +00:00
( empty ( $server [ 'HTTP_X_FORWARDED_PROTO' ]) || $server [ 'HTTP_X_FORWARDED_PROTO' ] === 'http' ) &&
2023-02-18 19:47:52 +00:00
! empty ( $server [ 'REQUEST_METHOD' ]) &&
$server [ 'REQUEST_METHOD' ] === 'GET' ) {
System :: externalRedirect ( $this -> baseURL . '/' . $this -> args -> getQueryString ());
2019-07-24 00:01:45 +00:00
}
Core\Hook :: callAll ( 'init_1' );
2019-03-19 06:44:51 +00:00
}
2020-10-02 09:31:39 +00:00
if ( $this -> mode -> isNormal () && ! $this -> mode -> isBackend ()) {
2019-07-24 00:01:45 +00:00
$requester = HTTPSignature :: getSigner ( '' , $_SERVER );
if ( ! empty ( $requester )) {
Profile :: addVisitorCookieForHandle ( $requester );
2018-10-22 02:24:47 +00:00
}
}
2019-07-24 00:01:45 +00:00
// ZRL
2022-10-23 18:41:17 +00:00
if ( ! empty ( $_GET [ 'zrl' ]) && $this -> mode -> isNormal () && ! $this -> mode -> isBackend () && ! $this -> session -> getLocalUserId ()) {
2022-12-08 03:24:01 +00:00
// Only continue when the given profile link seems valid.
2021-12-08 20:23:07 +00:00
// Valid profile links contain a path with "/profile/" and no query parameters
2022-06-24 01:01:13 +00:00
if (( parse_url ( $_GET [ 'zrl' ], PHP_URL_QUERY ) == '' ) &&
2022-12-08 03:24:01 +00:00
strpos ( parse_url ( $_GET [ 'zrl' ], PHP_URL_PATH ) ? ? '' , '/profile/' ) !== false ) {
2022-10-18 19:10:37 +00:00
if ( $this -> session -> get ( 'visitor_home' ) != $_GET [ 'zrl' ]) {
2022-10-18 19:12:23 +00:00
$this -> session -> set ( 'my_url' , $_GET [ 'zrl' ]);
$this -> session -> set ( 'authenticated' , 0 );
2021-12-08 20:23:07 +00:00
$remote_contact = Contact :: getByURL ( $_GET [ 'zrl' ], false , [ 'subscribe' ]);
if ( ! empty ( $remote_contact [ 'subscribe' ])) {
$_SESSION [ 'remote_comment' ] = $remote_contact [ 'subscribe' ];
2019-07-24 00:01:45 +00:00
}
}
2021-12-08 20:23:07 +00:00
Model\Profile :: zrlInit ( $this );
} else {
// Someone came with an invalid parameter, maybe as a DDoS attempt
// We simply stop processing here
$this -> logger -> debug ( 'Invalid ZRL parameter.' , [ 'zrl' => $_GET [ 'zrl' ]]);
throw new HTTPException\ForbiddenException ();
2019-07-24 00:01:45 +00:00
}
}
2018-10-22 02:24:47 +00:00
2019-08-15 14:18:08 +00:00
if ( ! empty ( $_GET [ 'owt' ]) && $this -> mode -> isNormal ()) {
2019-07-24 00:01:45 +00:00
$token = $_GET [ 'owt' ];
Model\Profile :: openWebAuthInit ( $token );
}
2018-10-22 02:24:47 +00:00
2021-10-25 03:17:22 +00:00
if ( ! $this -> mode -> isBackend ()) {
$auth -> withSession ( $this );
}
2018-10-22 02:24:47 +00:00
2019-07-24 00:01:45 +00:00
if ( empty ( $_SESSION [ 'authenticated' ])) {
header ( 'X-Account-Management-Status: none' );
}
2018-10-22 02:24:47 +00:00
2019-07-24 00:01:45 +00:00
/*
* check_config () is responsible for running update scripts . These automatically
* update the DB schema whenever we push a new one out . It also checks to see if
* any addons have been added or removed and reacts accordingly .
*/
// in install mode, any url loads install module
// but we need "view" module for stylesheet
2019-08-15 14:18:08 +00:00
if ( $this -> mode -> isInstall () && $moduleName !== 'install' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'install' );
2019-07-24 00:01:45 +00:00
} else {
2023-01-06 11:50:14 +00:00
Core\Update :: check ( $this -> getBasePath (), false );
2019-07-24 00:01:45 +00:00
Core\Addon :: loadAddons ();
Core\Hook :: loadHooks ();
}
2018-10-22 02:24:47 +00:00
2019-07-24 00:01:45 +00:00
// Compatibility with the Android Diaspora client
2019-08-12 16:13:58 +00:00
if ( $moduleName == 'stream' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'network?order=post' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if ( $moduleName == 'conversations' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'message' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if ( $moduleName == 'commented' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'network?order=comment' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if ( $moduleName == 'liked' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'network?order=comment' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if ( $moduleName == 'activity' ) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'network?conv=1' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if (( $moduleName == 'status_messages' ) && ( $this -> args -> getCommand () == 'status_messages/new' )) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'bookmarklet' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if (( $moduleName == 'user' ) && ( $this -> args -> getCommand () == 'user/edit' )) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'settings' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2019-08-12 16:13:58 +00:00
if (( $moduleName == 'tag_followings' ) && ( $this -> args -> getCommand () == 'tag_followings/manage' )) {
2019-12-15 23:28:31 +00:00
$this -> baseURL -> redirect ( 'search' );
2019-07-24 00:01:45 +00:00
}
2018-10-22 02:24:47 +00:00
2021-07-25 05:08:29 +00:00
// Initialize module that can set the current theme in the init() method, either directly or via App->setProfileOwner
2019-12-30 19:02:09 +00:00
$page [ 'page_title' ] = $moduleName ;
2019-08-15 18:58:57 +00:00
2022-07-12 23:48:36 +00:00
// The "view" module is required to show the theme CSS
if ( ! $this -> mode -> isInstall () && ! $this -> mode -> has ( App\Mode :: MAINTENANCEDISABLED ) && $moduleName !== 'view' ) {
2021-11-20 14:38:03 +00:00
$module = $router -> getModule ( Maintenance :: class );
2021-03-10 14:40:42 +00:00
} else {
// determine the module class and save it to the module instance
// @todo there's an implicit dependency due SESSION::start(), so it has to be called here (yet)
2021-11-19 21:47:49 +00:00
$module = $router -> getModule ();
2021-03-10 14:40:42 +00:00
}
2018-10-22 02:24:47 +00:00
2023-07-09 01:01:48 +00:00
// Display can change depending on the requested language, so it shouldn't be cached whole
header ( 'Vary: Accept-Language' , false );
2021-11-28 12:44:42 +00:00
// Processes data from GET requests
2021-11-28 13:01:13 +00:00
$httpinput = $httpInput -> process ();
$input = array_merge ( $httpinput [ 'variables' ], $httpinput [ 'files' ], $request ? ? $_REQUEST );
2021-11-28 12:44:42 +00:00
2022-12-26 20:17:32 +00:00
// Let the module run its internal process (init, get, post, ...)
2021-12-09 13:04:51 +00:00
$timestamp = microtime ( true );
2022-12-26 20:17:32 +00:00
$response = $module -> run ( $httpException , $input );
2021-12-09 13:04:51 +00:00
$this -> profiler -> set ( microtime ( true ) - $timestamp , 'content' );
2023-07-10 02:44:40 +00:00
// Wrapping HTML responses in the theme template
2021-11-21 23:07:09 +00:00
if ( $response -> getHeaderLine ( ICanCreateResponses :: X_HEADER ) === ICanCreateResponses :: TYPE_HTML ) {
2023-07-10 02:44:40 +00:00
$response = $page -> run ( $this , $this -> baseURL , $this -> args , $this -> mode , $response , $this -> l10n , $this -> profiler , $this -> config , $pconfig , $nav , $this -> session -> getLocalUserId ());
2021-11-21 20:52:36 +00:00
}
2023-07-10 02:44:40 +00:00
2023-09-11 10:18:02 +00:00
$this -> logger -> debug ( 'Request processed sucessfully' , [ 'response' => $response -> getStatusCode (), 'address' => $_SERVER [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $_SERVER [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $_SERVER [ 'HTTP_USER_AGENT' ] ? ? '' ]);
2023-09-21 13:17:38 +00:00
System :: echoResponse ( $response );
2019-08-15 14:18:08 +00:00
} catch ( HTTPException $e ) {
2023-09-11 10:18:02 +00:00
$this -> logger -> debug ( 'Request processed with exception' , [ 'response' => $e -> getCode (), 'address' => $_SERVER [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $_SERVER [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $_SERVER [ 'HTTP_USER_AGENT' ] ? ? '' ]);
2022-12-26 20:17:32 +00:00
$httpException -> rawContent ( $e );
2019-05-02 01:33:33 +00:00
}
2022-06-10 18:49:03 +00:00
$page -> logRuntime ( $this -> config , 'runFrontend' );
2018-10-20 16:19:55 +00:00
}
2018-10-13 18:02:04 +00:00
2018-10-24 18:16:14 +00:00
/**
2018-10-24 18:52:38 +00:00
* Automatically redirects to relative or absolute URL
2018-10-24 18:16:14 +00:00
* Should only be used if it isn ' t clear if the URL is either internal or external
*
* @ param string $toUrl The target URL
2019-08-15 14:18:08 +00:00
*
2019-05-02 01:33:33 +00:00
* @ throws HTTPException\InternalServerErrorException
2018-10-24 18:16:14 +00:00
*/
2022-06-16 14:25:30 +00:00
public function redirect ( string $toUrl )
2018-10-24 18:16:14 +00:00
{
2018-11-30 11:27:17 +00:00
if ( ! empty ( parse_url ( $toUrl , PHP_URL_SCHEME ))) {
2018-10-24 18:24:22 +00:00
Core\System :: externalRedirect ( $toUrl );
2018-10-24 18:16:14 +00:00
} else {
2019-12-03 20:11:42 +00:00
$this -> baseURL -> redirect ( $toUrl );
2018-10-24 18:16:14 +00:00
}
}
2017-05-08 06:11:38 +00:00
}