Merge develop into 20180425_-_fix_help_aside

This commit is contained in:
rabuzarus
2018-04-30 14:56:25 +02:00
84 changed files with 26334 additions and 25911 deletions
+2 -1
View File
@@ -9,6 +9,7 @@ include/jquery-1.4.2.min.js
favicon.*
home.html
addon
*.orig
*~
robots.txt
@@ -57,4 +58,4 @@ venv/
/view/asset
#ignore config files from JetBrains
/.idea
/.idea
+1 -109
View File
@@ -1018,114 +1018,6 @@ function get_max_import_size()
return (x($a->config, 'max_import_size') ? $a->config['max_import_size'] : 0);
}
function current_theme()
{
$app_base_themes = ['duepuntozero', 'dispy', 'quattro'];
$a = get_app();
$page_theme = null;
// Find the theme that belongs to the user whose stuff we are looking at
if ($a->profile_uid && ($a->profile_uid != local_user())) {
$r = q(
"select theme from user where uid = %d limit 1",
intval($a->profile_uid)
);
if (DBM::is_result($r)) {
$page_theme = $r[0]['theme'];
}
}
// Allow folks to over-rule user themes and always use their own on their own site.
// This works only if the user is on the same server
if ($page_theme && local_user() && (local_user() != $a->profile_uid)) {
if (PConfig::get(local_user(), 'system', 'always_my_theme')) {
$page_theme = null;
}
}
// $mobile_detect = new Mobile_Detect();
// $is_mobile = $mobile_detect->isMobile() || $mobile_detect->isTablet();
$is_mobile = $a->is_mobile || $a->is_tablet;
$standard_system_theme = Config::get('system', 'theme', '');
$standard_theme_name = ((isset($_SESSION) && x($_SESSION, 'theme')) ? $_SESSION['theme'] : $standard_system_theme);
if ($is_mobile) {
if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
$theme_name = $standard_theme_name;
} else {
$system_theme = Config::get('system', 'mobile-theme', '');
if ($system_theme == '') {
$system_theme = $standard_system_theme;
}
$theme_name = ((isset($_SESSION) && x($_SESSION, 'mobile-theme')) ? $_SESSION['mobile-theme'] : $system_theme);
if ($theme_name === '---') {
// user has selected to have the mobile theme be the same as the normal one
$theme_name = $standard_theme_name;
if ($page_theme) {
$theme_name = $page_theme;
}
}
}
} else {
$theme_name = $standard_theme_name;
if ($page_theme) {
$theme_name = $page_theme;
}
}
if ($theme_name
&& (file_exists('view/theme/' . $theme_name . '/style.css')
|| file_exists('view/theme/' . $theme_name . '/style.php'))
) {
return($theme_name);
}
foreach ($app_base_themes as $t) {
if (file_exists('view/theme/' . $t . '/style.css')
|| file_exists('view/theme/' . $t . '/style.php')
) {
return($t);
}
}
$fallback = array_merge(glob('view/theme/*/style.css'), glob('view/theme/*/style.php'));
if (count($fallback)) {
return (str_replace('view/theme/', '', substr($fallback[0], 0, -10)));
}
/// @TODO No final return statement?
}
/**
* @brief Return full URL to theme which is currently in effect.
*
* Provide a sane default if nothing is chosen or the specified theme does not exist.
*
* @return string
*/
function current_theme_url()
{
$a = get_app();
$t = current_theme();
$opts = (($a->profile_uid) ? '?f=&puid=' . $a->profile_uid : '');
if (file_exists('view/theme/' . $t . '/style.php')) {
return('view/theme/' . $t . '/style.pcss' . $opts);
}
return('view/theme/' . $t . '/style.css');
}
function feed_birthday($uid, $tz)
{
/**
@@ -1292,7 +1184,7 @@ function get_server()
$server = Config::get("system", "directory");
if ($server == "") {
$server = "http://dir.friendica.social";
$server = "https://dir.friendica.social";
}
return($server);
+7 -3
View File
@@ -470,11 +470,15 @@ These Fields are not added below (yet). They are here to for bug search.
* @brief SQL join for contacts that are needed for displaying items
*/
function item_joins() {
return "STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND
(NOT `contact`.`blocked` OR `contact`.`pending`)
return sprintf("STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked`
AND ((NOT `contact`.`readonly` AND NOT `contact`.`pending` AND (`contact`.`rel` IN (%s, %s)))
OR `contact`.`self` OR (`item`.`id` != `item`.`parent`))
LEFT JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
LEFT JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id`
LEFT JOIN `event` ON `event-id` = `event`.`id`";
LEFT JOIN `event` ON `event-id` = `event`.`id`",
CONTACT_IS_SHARING, CONTACT_IS_FRIEND
);
}
/**
+4 -2
View File
@@ -1,5 +1,6 @@
<?php
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
@@ -24,7 +25,7 @@ class dba {
private static $in_transaction = false;
private static $relation = [];
public static function connect($serveraddr, $user, $pass, $db, $install = false) {
public static function connect($serveraddr, $user, $pass, $db) {
if (!is_null(self::$db)) {
return true;
}
@@ -51,7 +52,7 @@ class dba {
return false;
}
if ($install) {
if ($a->mode == App::MODE_INSTALL) {
// server has to be a non-empty string that is not 'localhost' and not an IP
if (strlen($server) && ($server !== 'localhost') && filter_var($server, FILTER_VALIDATE_IP) === false) {
if (! dns_get_record($server, DNS_A + DNS_CNAME)) {
@@ -93,6 +94,7 @@ class dba {
// No suitable SQL driver was found.
if (!self::$connected) {
self::$driver = null;
self::$db = null;
}
$a->save_timestamp($stamp1, "network");
+4 -4
View File
@@ -513,7 +513,7 @@ function load_view_file($s) {
return $content;
}
$theme = current_theme();
$theme = $a->getCurrentTheme();
if (file_exists("$d/theme/$theme/$b")) {
$stamp1 = microtime(true);
@@ -637,7 +637,7 @@ function logger($msg, $level = 0) {
// turn off logger in install mode
if (
$a->module == 'install'
$a->mode == App::MODE_INSTALL
|| !dba::$connected
) {
return;
@@ -709,7 +709,7 @@ function dlogger($msg, $level = 0) {
// turn off logger in install mode
if (
$a->module == 'install'
$a->mode == App::MODE_INSTALL
|| !dba::$connected
) {
return;
@@ -1249,7 +1249,7 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
// Compile eventual content filter reasons
$filter_reasons = [];
if (!$is_preview && !($item['self'] && local_user() == $item['uid'])) {
if (!$is_preview && public_contact() != $item['author-id']) {
if (!empty($item['content-warning']) && (!local_user() || !PConfig::get(local_user(), 'system', 'disable_cw', false))) {
$filter_reasons[] = L10n::t('Content warning: %s', $item['content-warning']);
}
+14 -22
View File
@@ -31,16 +31,8 @@ BaseObject::setApp($a);
// The value is set to "true" by default in boot.php
$a->backend = false;
/**
* Load the configuration file which contains our DB credentials.
* Ignore errors. If the file doesn't exist or is empty, we are running in
* installation mode.
*/
$install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false : true);
// Only load config if found, don't surpress errors
if (!$install) {
// Only load config if found, don't suppress errors
if (!$a->mode == App::MODE_INSTALL) {
include ".htconfig.php";
}
@@ -50,7 +42,7 @@ if (!$install) {
require_once "include/dba.php";
if (!$install) {
if (!$a->mode == App::MODE_INSTALL) {
$result = dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
@@ -85,7 +77,7 @@ if (!$install) {
Addon::loadHooks();
Addon::callHooks('init_1');
$maintenance = Config::get('system', 'maintenance');
$a->checkMaintenanceMode();
}
$lang = L10n::getBrowserLanguage();
@@ -129,7 +121,7 @@ if ((x($_SESSION, 'language')) && ($_SESSION['language'] !== $lang)) {
L10n::loadTranslationTable($lang);
}
if ((x($_GET, 'zrl')) && (!$install && !$maintenance)) {
if ((x($_GET, 'zrl')) && $a->mode == App::MODE_NORMAL) {
// Only continue when the given profile link seems valid
// Valid profile links contain a path with "/profile/" and no query parameters
if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "")
@@ -181,9 +173,9 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
// in install mode, any url loads install module
// but we need "view" module for stylesheet
if ($install && $a->module!="view") {
if ($a->mode == App::MODE_INSTALL && $a->module!="view") {
$a->module = 'install';
} elseif ($maintenance && $a->module!="view") {
} elseif ($a->mode == App::MODE_MAINTENANCE && $a->module!="view") {
$a->module = 'maintenance';
} else {
check_url($a);
@@ -330,7 +322,7 @@ if (strlen($a->module)) {
/**
* Load current theme info
*/
$theme_info_file = "view/theme/".current_theme()."/theme.php";
$theme_info_file = 'view/theme/' . $a->getCurrentTheme() . '/theme.php';
if (file_exists($theme_info_file)) {
require_once $theme_info_file;
}
@@ -342,7 +334,7 @@ if (! x($a->page, 'content')) {
$a->page['content'] = '';
}
if (!$install && !$maintenance) {
if ($a->mode == App::MODE_NORMAL) {
Addon::callHooks('page_content_top', $a->page['content']);
}
@@ -363,8 +355,8 @@ if ($a->module_loaded) {
$func($a);
}
if (function_exists(str_replace('-', '_', current_theme()) . '_init')) {
$func = str_replace('-', '_', current_theme()) . '_init';
if (function_exists(str_replace('-', '_', $a->getCurrentTheme()) . '_init')) {
$func = str_replace('-', '_', $a->getCurrentTheme()) . '_init';
$func($a);
}
@@ -402,8 +394,8 @@ if ($a->module_loaded) {
$a->page['content'] .= $arr['content'];
}
if (function_exists(str_replace('-', '_', current_theme()) . '_content_loaded')) {
$func = str_replace('-', '_', current_theme()) . '_content_loaded';
if (function_exists(str_replace('-', '_', $a->getCurrentTheme()) . '_content_loaded')) {
$func = str_replace('-', '_', $a->getCurrentTheme()) . '_content_loaded';
$func($a);
}
}
@@ -478,7 +470,7 @@ if ($a->is_mobile || $a->is_tablet) {
*/
if (!$a->theme['stylesheet']) {
$stylesheet = current_theme_url();
$stylesheet = $a->getCurrentThemeStylesheetPath();
} else {
$stylesheet = $a->theme['stylesheet'];
}
+1
View File
@@ -1120,6 +1120,7 @@ function admin_page_site_post(App $a)
}
Config::set('system', 'language', $language);
Config::set('system', 'theme', $theme);
Theme::install($theme);
if ($theme_mobile == '---') {
Config::delete('system', 'mobile-theme');
+7 -298
View File
@@ -5,11 +5,9 @@
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\Install;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Database\DBStructure;
use Friendica\Object\Image;
use Friendica\Util\Network;
use Friendica\Util\Temporal;
$install_wizard_pass = 1;
@@ -27,6 +25,8 @@ function install_init(App $a) {
$a->config['system']['theme'] = "../install";
$a->theme['stylesheet'] = System::baseUrl()."/view/install/style.css";
Install::setInstallMode();
global $install_wizard_pass;
if (x($_POST, 'pass')) {
$install_wizard_pass = intval($_POST['pass']);
@@ -51,7 +51,7 @@ function install_post(App $a) {
$phpath = notags(trim($_POST['phpath']));
require_once("include/dba.php");
if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true)) {
if (!dba::connect($dbhost, $dbuser, $dbpass, $dbdata)) {
$a->data['db_conn_failed'] = true;
}
@@ -70,36 +70,9 @@ function install_post(App $a) {
$rino = 1;
// connect to db
dba::connect($dbhost, $dbuser, $dbpass, $dbdata, true);
dba::connect($dbhost, $dbuser, $dbpass, $dbdata);
$tpl = get_markup_template('htconfig.tpl');
$txt = replace_macros($tpl,[
'$dbhost' => $dbhost,
'$dbuser' => $dbuser,
'$dbpass' => $dbpass,
'$dbdata' => $dbdata,
'$timezone' => $timezone,
'$language' => $language,
'$urlpath' => $urlpath,
'$phpath' => $phpath,
'$adminmail' => $adminmail,
'$rino' => $rino
]);
$result = file_put_contents('.htconfig.php', $txt);
if (! $result) {
$a->data['txt'] = $txt;
}
$errors = load_database();
if ($errors) {
$a->data['db_failed'] = $errors;
} else {
$a->data['db_installed'] = true;
}
Install::install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino);
return;
break;
@@ -167,37 +140,11 @@ function install_content(App $a) {
switch ($install_wizard_pass) {
case 1: { // System check
$checks = [];
check_funcs($checks);
check_imagik($checks);
check_htconfig($checks);
check_smarty3($checks);
check_keys($checks);
if (x($_POST, 'phpath')) {
$phpath = notags(trim($_POST['phpath']));
}
check_php($phpath, $checks);
check_htaccess($checks);
/// @TODO Maybe move this out?
function check_passed($v, $c) {
if ($c['required']) {
$v = $v && $c['status'];
}
return $v;
}
$checkspassed = array_reduce($checks, "check_passed", true);
list($checks, $checkspassed) = Install::check($phpath);
$tpl = get_markup_template('install_checks.tpl');
$o .= replace_macros($tpl, [
@@ -296,238 +243,6 @@ function install_content(App $a) {
}
}
/**
* checks : array passed to template
* title : string
* status : boolean
* required : boolean
* help : string optional
*/
function check_add(&$checks, $title, $status, $required, $help) {
$checks[] = [
'title' => $title,
'status' => $status,
'required' => $required,
'help' => $help,
];
}
function check_php(&$phpath, &$checks) {
$passed = $passed2 = $passed3 = false;
if (strlen($phpath)) {
$passed = file_exists($phpath);
} else {
$phpath = trim(shell_exec('which php'));
$passed = strlen($phpath);
}
$help = "";
if (!$passed) {
$help .= L10n::t('Could not find a command line version of PHP in the web server PATH.'). EOL;
$help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . EOL;
$help .= EOL . EOL;
$tpl = get_markup_template('field_input.tpl');
$help .= replace_macros($tpl, [
'$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
]);
$phpath = "";
}
check_add($checks, L10n::t('Command line PHP').($passed?" (<tt>$phpath</tt>)":""), $passed, false, $help);
if ($passed) {
$cmd = "$phpath -v";
$result = trim(shell_exec($cmd));
$passed2 = ( strpos($result, "(cli)") !== false);
list($result) = explode("\n", $result);
$help = "";
if (!$passed2) {
$help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29"). EOL;
$help .= L10n::t('Found PHP version: ')."<tt>$result</tt>";
}
check_add($checks, L10n::t('PHP cli binary'), $passed2, true, $help);
}
if ($passed2) {
$str = autoname(8);
$cmd = "$phpath testargs.php $str";
$result = trim(shell_exec($cmd));
$passed3 = $result == $str;
$help = "";
if (!$passed3) {
$help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.'). EOL;
$help .= L10n::t('This is required for message delivery to work.');
}
check_add($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help);
}
}
function check_keys(&$checks) {
$help = '';
$res = false;
if (function_exists('openssl_pkey_new')) {
$res = openssl_pkey_new([
'digest_alg' => 'sha1',
'private_key_bits' => 4096,
'encrypt_key' => false
]);
}
// Get private key
if (! $res) {
$help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys'). EOL;
$help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
}
check_add($checks, L10n::t('Generate encryption keys'), $res, true, $help);
}
function check_funcs(&$checks) {
$ck_funcs = [];
check_add($ck_funcs, L10n::t('libCurl PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('GD graphics PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('mb_string PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('XML PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('iconv PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('POSIX PHP module'), true, true, "");
if (function_exists('apache_get_modules')) {
if (! in_array('mod_rewrite',apache_get_modules())) {
check_add($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.'));
} else {
check_add($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, "");
}
}
if (! function_exists('curl_init')) {
$ck_funcs[0]['status'] = false;
$ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.');
}
if (! function_exists('imagecreatefromjpeg')) {
$ck_funcs[1]['status'] = false;
$ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.');
}
if (! function_exists('openssl_public_encrypt')) {
$ck_funcs[2]['status'] = false;
$ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.');
}
if (! function_exists('mysqli_connect') && !class_exists('pdo')) {
$ck_funcs[3]['status'] = false;
$ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
}
if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', PDO::getAvailableDrivers())) {
$ck_funcs[3]['status'] = false;
$ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.');
}
if (! function_exists('mb_strlen')) {
$ck_funcs[4]['status'] = false;
$ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.');
}
if (! function_exists('iconv_strlen')) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.');
}
if (! function_exists('posix_kill')) {
$ck_funcs[7]['status'] = false;
$ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);
// check for XML DOM Documents being able to be generated
try {
$xml = new DOMDocument();
} catch (Exception $e) {
$ck_funcs[5]['status'] = false;
$ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.');
}
}
function check_htconfig(&$checks) {
$status = true;
$help = "";
if ((file_exists('.htconfig.php') && !is_writable('.htconfig.php')) ||
(!file_exists('.htconfig.php') && !is_writable('.'))) {
$status = false;
$help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') .EOL;
$help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.').EOL;
$help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica top folder.').EOL;
$help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.').EOL;
}
check_add($checks, L10n::t('.htconfig.php is writable'), $status, false, $help);
}
function check_smarty3(&$checks) {
$status = true;
$help = "";
if (!is_writable('view/smarty3')) {
$status = false;
$help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') .EOL;
$help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.').EOL;
$help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.").EOL;
$help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.").EOL;
}
check_add($checks, L10n::t('view/smarty3 is writable'), $status, true, $help);
}
function check_htaccess(&$checks) {
$status = true;
$help = "";
if (function_exists('curl_init')) {
$test = Network::fetchUrl(System::baseUrl()."/install/testrewrite");
if ($test != "ok") {
$test = Network::fetchUrl(normalise_link(System::baseUrl()."/install/testrewrite"));
}
if ($test != "ok") {
$status = false;
$help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.');
}
check_add($checks, L10n::t('Url rewrite is working'), $status, true, $help);
} else {
// cannot check modrewrite if libcurl is not installed
/// @TODO Maybe issue warning here?
}
}
function check_imagik(&$checks) {
$imagick = false;
$gif = false;
if (class_exists('Imagick')) {
$imagick = true;
$supported = Image::supportedTypes();
if (array_key_exists('image/gif', $supported)) {
$gif = true;
}
}
if ($imagick == false) {
check_add($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
} else {
check_add($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
if ($imagick) {
check_add($checks, L10n::t('ImageMagick supports GIF'), $gif, false, "");
}
}
}
function manual_config(App $a) {
$data = htmlentities($a->data['txt'],ENT_COMPAT, 'UTF-8');
$o = L10n::t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
@@ -544,12 +259,6 @@ function load_database_rem($v, $i) {
}
}
function load_database() {
$errors = DBStructure::update(false, true, true);
return $errors;
}
function what_next() {
$baseurl = System::baseUrl();
return
+8 -7
View File
@@ -836,14 +836,10 @@ function networkThreadedView(App $a, $update, $parent)
STRAIGHT_JOIN (SELECT `oid` FROM `term` WHERE `term` IN
(SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `otype` = ? AND `type` = ? AND `uid` = 0) AS `term`
ON `item`.`id` = `term`.`oid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`author-id`
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (?, ?) AND NOT `contact`.`readonly`)
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `item`.`author-id`
WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ?
AND NOT `contact`.`hidden` AND NOT `contact`.`blocked`" . $sql_tag_nets,
AND NOT `author`.`hidden` AND NOT `author`.`blocked`" . $sql_tag_nets,
local_user(), TERM_OBJ_POST, TERM_HASHTAG,
CONTACT_IS_SHARING, CONTACT_IS_FRIEND,
$top_limit, $bottom_limit);
$data = dba::inArray($items);
@@ -860,7 +856,12 @@ function networkThreadedView(App $a, $update, $parent)
$s[$item['uri']] = $item;
}
foreach ($data as $item) {
$s[$item['uri']] = $item;
// Don't show hash tag posts from blocked or ignored contacts
$condition = ["`nurl` = ? AND `uid` = ? AND (`blocked` OR `readonly`)",
normalise_link($item['author-link']), local_user()];
if (!dba::exists('contact', $condition)) {
$s[$item['uri']] = $item;
}
}
$r = $s;
}
+2
View File
@@ -12,6 +12,7 @@ use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Core\Theme;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
@@ -354,6 +355,7 @@ function settings_post(App $a)
theme_post($a);
}
}
Theme::install($theme);
$r = q("UPDATE `user` SET `theme` = '%s' WHERE `uid` = %d",
dbesc($theme),
+109
View File
@@ -32,6 +32,10 @@ require_once 'include/text.php';
*/
class App
{
const MODE_NORMAL = 0;
const MODE_INSTALL = 1;
const MODE_MAINTENANCE = 2;
public $module_loaded = false;
public $module_class = null;
public $query_string;
@@ -52,6 +56,7 @@ class App
public $argv;
public $argc;
public $module;
public $mode = App::MODE_NORMAL;
public $pager;
public $strings;
public $basepath;
@@ -288,6 +293,14 @@ class App
// Register template engines
$this->register_template_engine('Friendica\Render\FriendicaSmartyEngine');
/**
* Load the configuration file which contains our DB credentials.
* Ignore errors. If the file doesn't exist or is empty, we are running in
* installation mode. *
*/
$this->mode = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? App::MODE_NORMAL : App::MODE_INSTALL);
self::$a = $this;
}
@@ -1067,4 +1080,100 @@ class App
return $sender_email;
}
/**
* @note Checks, if the App is in the Maintenance-Mode
*
* @return boolean
*/
public function checkMaintenanceMode()
{
if (Config::get('system', 'maintenance')) {
$this->mode = App::MODE_MAINTENANCE;
return true;
}
return false;
}
/**
* Returns the current theme name.
*
* @return string
*/
public function getCurrentTheme()
{
if (!$this->current_theme) {
$this->computeCurrentTheme();
}
return $this->current_theme;
}
/**
* Computes the current theme name based on the node settings, the user settings and the device type
*
* @throws Exception
*/
private function computeCurrentTheme()
{
$system_theme = Config::get('system', 'theme');
if (!$system_theme) {
throw new Exception(L10n::t('No system theme config value set.'));
}
// Sane default
$this->current_theme = $system_theme;
$allowed_themes = explode(',', Config::get('system', 'allowed_themes', $system_theme));
$page_theme = null;
// Find the theme that belongs to the user whose stuff we are looking at
if ($this->profile_uid && ($this->profile_uid != local_user())) {
// 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
$user = dba::selectFirst('user', ['theme'], ['uid' => $this->profile_uid]);
if (DBM::is_result($user) && !PConfig::get(local_user(), 'system', 'always_my_theme')) {
$page_theme = $user['theme'];
}
}
$user_theme = defaults($_SESSION, 'theme', $system_theme);
// Specific mobile theme override
if (($this->is_mobile || $this->is_tablet) && defaults($_SESSION, 'show-mobile', true)) {
$system_mobile_theme = Config::get('system', 'mobile-theme');
$user_mobile_theme = defaults($_SESSION, 'mobile-theme', $system_mobile_theme);
// --- means same mobile theme as desktop
if (!empty($user_mobile_theme) && $user_mobile_theme !== '---') {
$user_theme = $user_mobile_theme;
}
}
if ($page_theme) {
$theme_name = $page_theme;
} else {
$theme_name = $user_theme;
}
if ($theme_name
&& in_array($theme_name, $allowed_themes)
&& (file_exists('view/theme/' . $theme_name . '/style.css')
|| file_exists('view/theme/' . $theme_name . '/style.php'))
) {
$this->current_theme = $theme_name;
}
}
/**
* @brief Return full URL to theme which is currently in effect.
*
* Provide a sane default if nothing is chosen or the specified theme does not exist.
*
* @return string
*/
public function getCurrentThemeStylesheetPath()
{
return Core\Theme::getStylesheetPath($this->getCurrentTheme());
}
}
+6 -5
View File
@@ -228,14 +228,15 @@ class Addon
/**
* @brief Calls a single hook.
*
* @param string $name of the hook to call
* @param array $hook Hook data
* @param string|array &$data to transmit to the callback handler
* @param \Friendica\App $a
* @param string $name of the hook to call
* @param array $hook Hook data
* @param string|array &$data to transmit to the callback handler
*/
public static function callSingleHook($a, $name, $hook, &$data = null)
public static function callSingleHook(\Friendica\App $a, $name, $hook, &$data = null)
{
// Don't run a theme's hook if the user isn't using the theme
if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/'.current_theme()) === false) {
if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/' . $a->getCurrentTheme()) === false) {
return;
}
+11 -8
View File
@@ -5,6 +5,7 @@ namespace Friendica\Core\Console;
use Asika\SimpleConsole\Console;
use dba;
use Friendica\App;
use Friendica\Core\Install;
require_once 'mod/install.php';
require_once 'include/dba.php';
@@ -43,6 +44,8 @@ HELP;
$db_data = '';
require_once 'htconfig.php';
Install::setInstallMode();
$this->out(" Complete!\n\n");
// Check basic setup
@@ -74,7 +77,7 @@ HELP;
// Install database
$this->out("Inserting data into database...\n");
$checkResults['data'] = load_database();
$checkResults['data'] = Install::installDatabaseStructure();
if ($checkResults['data'] !== '') {
throw new \RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n");
@@ -101,14 +104,14 @@ HELP;
{
$checks = [];
check_funcs($checks);
check_imagik($checks);
check_htconfig($checks);
check_smarty3($checks);
check_keys($checks);
Install::checkFunctions($checks);
Install::checkImagick($checks);
Install::checkHtConfig($checks);
Install::checkSmarty3($checks);
Install::checkKeys($checks);
if (!empty($app->config['php_path'])) {
check_php($app->config['php_path'], $checks);
Install::checkPHP($app->config['php_path'], $checks);
} else {
throw new \RuntimeException(" ERROR: The php_path is not set in the config. Please check the file .htconfig.php.\n");
}
@@ -135,7 +138,7 @@ HELP;
);
if (!dba::connect($db_host, $db_user, $db_pass, $db_data, true)) {
if (!dba::connect($db_host, $db_user, $db_pass, $db_data)) {
$result['status'] = false;
$result['help'] = 'Failed, please check your MySQL settings and credentials.';
}
+428
View File
@@ -0,0 +1,428 @@
<?php
/**
* @file src/Core/Install.php
*/
namespace Friendica\Core;
use Friendica\BaseObject;
use Friendica\App;
use Friendica\Database\DBStructure;
use Friendica\Object\Image;
use Friendica\Util\Network;
use Exception;
use DOMDocument;
/**
* Contains methods for installation purpose of Friendica
*/
class Install extends BaseObject
{
/**
* Sets the install-mode for further methods
*/
public static function setInstallMode()
{
self::getApp()->mode = App::MODE_INSTALL;
}
/**
* Checks the current installation environment. There are optional and mandatory checks.
*
* @param string $phpath Optional path to the PHP binary (Default is 'php')
*
* @return array First element is a list of all checks and their results,
* the second element is a list of passed checks
*/
public static function check($phpath = 'php')
{
$checks = [];
self::checkFunctions($checks);
self::checkImagick($checks);
self::checkHtConfig($checks);
self::checkSmarty3($checks);
self::checkKeys($checks);
self::checkPHP($phpath, $checks);
self::checkHtAccess($checks);
$checkspassed = array_reduce($checks,
function ($v, $c) {
if ($c['require']) {
$v = $v && $c['status'];
}
return $v;
},
true);
return array($checks, $checkspassed);
}
/**
* Executes the installation of Friendica in the given environment.
* - Creates `.htconfig.php`
* - Installs Database Structure
*
* @param string $urlpath Path based on the URL of Friendica (e.g. '/friendica')
* @param string $dbhost Hostname/IP of the Friendica Database
* @param string $dbuser Username of the Database connection credentials
* @param string $dbpass Password of the Database connection credentials
* @param string $dbdata Name of the Database
* @param string $phpath Path to the PHP-Binary (e.g. 'php' or '/usr/bin/php')
* @param string $timezone Timezone of the Friendica Installaton (e.g. 'Europe/Berlin')
* @param string $language 2-letter ISO 639-1 code (eg. 'en')
* @param string $adminmail Mail-Adress of the administrator
* @param int $rino Rino-enabled (1 = true, 0 = false)
*/
public static function install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail, $rino = 1)
{
$tpl = get_markup_template('htconfig.tpl');
$txt = replace_macros($tpl,[
'$dbhost' => $dbhost,
'$dbuser' => $dbuser,
'$dbpass' => $dbpass,
'$dbdata' => $dbdata,
'$timezone' => $timezone,
'$language' => $language,
'$urlpath' => $urlpath,
'$phpath' => $phpath,
'$adminmail' => $adminmail,
'$rino' => $rino
]);
$result = file_put_contents('.htconfig.php', $txt);
if (! $result) {
self::getApp()->data['txt'] = $txt;
}
$errors = self::installDatabaseStructure();
if ($errors) {
self::getApp()->data['db_failed'] = $errors;
} else {
self::getApp()->data['db_installed'] = true;
}
}
/**
* Adds new checks to the array $checks
*
* @param array $checks The list of all checks (by-ref parameter!)
* @param string $title The title of the current check
* @param bool $status 1 = check passed, 0 = check not passed
* @param bool $required 1 = check is mandatory, 0 = check is optional
* @param string $help A help-string for the current check
* @param string $error_msg Optional. A error message, if the current check failed
*/
private static function addCheck(&$checks, $title, $status, $required, $help, $error_msg = "")
{
$checks[] = [
'title' => $title,
'status' => $status,
'required' => $required,
'help' => $help,
'error_msg' => $error_msg,
];
}
/**
* PHP Check
*
* Checks the PHP environment.
*
* - Checks if a PHP binary is available
* - Checks if it is the CLI version
* - Checks if "register_argc_argv" is enabled
*
* @param string $phpath Optional. The Path to the PHP-Binary
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkPHP(&$phpath, &$checks)
{
$passed = $passed2 = $passed3 = false;
if (strlen($phpath)) {
$passed = file_exists($phpath);
} else {
$phpath = trim(shell_exec('which php'));
$passed = strlen($phpath);
}
$help = "";
if (!$passed) {
$help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL;
$help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . EOL;
$help .= EOL . EOL;
$tpl = get_markup_template('field_input.tpl');
$help .= replace_macros($tpl, [
'$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
]);
$phpath = "";
}
self::addCheck($checks, L10n::t('Command line PHP').($passed?" (<tt>$phpath</tt>)":""), $passed, false, $help);
if ($passed) {
$cmd = "$phpath -v";
$result = trim(shell_exec($cmd));
$passed2 = (strpos($result, "(cli)") !== false);
list($result) = explode("\n", $result);
$help = "";
if (!$passed2) {
$help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL;
$help .= L10n::t('Found PHP version: ') . "<tt>$result</tt>";
}
self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help);
}
if ($passed2) {
$str = autoname(8);
$cmd = "$phpath testargs.php $str";
$result = trim(shell_exec($cmd));
$passed3 = $result == $str;
$help = "";
if (!$passed3) {
$help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL;
$help .= L10n::t('This is required for message delivery to work.');
}
self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help);
}
}
/**
* OpenSSL Check
*
* Checks the OpenSSL Environment
*
* - Checks, if the command "openssl_pkey_new" is available
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkKeys(&$checks)
{
$help = '';
$res = false;
if (function_exists('openssl_pkey_new')) {
$res = openssl_pkey_new([
'digest_alg' => 'sha1',
'private_key_bits' => 4096,
'encrypt_key' => false
]);
}
// Get private key
if (!$res) {
$help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL;
$help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
}
self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help);
}
/**
* PHP functions Check
*
* Checks the following PHP functions
* - libCurl
* - GD Graphics
* - OpenSSL
* - PDO or MySQLi
* - mb_string
* - XML
* - iconv
* - POSIX
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkFunctions(&$checks)
{
$ck_funcs = [];
self::addCheck($ck_funcs, L10n::t('libCurl PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('GD graphics PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('mb_string PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('XML PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('iconv PHP module'), true, true, "");
self::addCheck($ck_funcs, L10n::t('POSIX PHP module'), true, true, "");
if (function_exists('apache_get_modules')) {
if (! in_array('mod_rewrite',apache_get_modules())) {
self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.'));
} else {
self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, "");
}
}
if (!function_exists('curl_init')) {
$ck_funcs[0]['status'] = false;
$ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.');
}
if (!function_exists('imagecreatefromjpeg')) {
$ck_funcs[1]['status'] = false;
$ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.');
}
if (!function_exists('openssl_public_encrypt')) {
$ck_funcs[2]['status'] = false;
$ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.');
}
if (!function_exists('mysqli_connect') && !class_exists('pdo')) {
$ck_funcs[3]['status'] = false;
$ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
}
if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', PDO::getAvailableDrivers())) {
$ck_funcs[3]['status'] = false;
$ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.');
}
if (!function_exists('mb_strlen')) {
$ck_funcs[4]['status'] = false;
$ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.');
}
if (!function_exists('iconv_strlen')) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.');
}
if (!function_exists('posix_kill')) {
$ck_funcs[7]['status'] = false;
$ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);
// check for XML DOM Documents being able to be generated
try {
$xml = new DOMDocument();
} catch (Exception $e) {
$ck_funcs[5]['status'] = false;
$ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.');
}
}
/**
* ".htconfig.php" - Check
*
* Checks if it's possible to create the ".htconfig.php"
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkHtConfig(&$checks)
{
$status = true;
$help = "";
if ((file_exists('.htconfig.php') && !is_writable('.htconfig.php')) ||
(!file_exists('.htconfig.php') && !is_writable('.'))) {
$status = false;
$help = L10n::t('The web installer needs to be able to create a file called ".htconfig.php" in the top folder of your web server and it is unable to do so.') . EOL;
$help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL;
$help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica top folder.') . EOL;
$help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL;
}
self::addCheck($checks, L10n::t('.htconfig.php is writable'), $status, false, $help);
}
/**
* Smarty3 Template Check
*
* Checks, if the directory of Smarty3 is writable
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkSmarty3(&$checks)
{
$status = true;
$help = "";
if (!is_writable('view/smarty3')) {
$status = false;
$help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL;
$help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL;
$help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL;
$help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL;
}
self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help);
}
/**
* ".htaccess" - Check
*
* Checks, if "url_rewrite" is enabled in the ".htaccess" file
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkHtAccess(&$checks)
{
$status = true;
$help = "";
$error_msg = "";
if (function_exists('curl_init')) {
$test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite");
$url = normalise_link(System::baseUrl() . "/install/testrewrite");
if ($test['body'] != "ok") {
$test = Network::fetchUrlFull($url);
}
if ($test['body'] != "ok") {
$status = false;
$help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.');
$error_msg = [];
$error_msg['head'] = L10n::t('Error message from Curl when fetching');
$error_msg['url'] = $test['redirect_url'];
$error_msg['msg'] = $test['error'];
}
self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help, $error_msg);
} else {
// cannot check modrewrite if libcurl is not installed
/// @TODO Maybe issue warning here?
}
}
/**
* Imagick Check
*
* Checks, if the imagick module is available
*
* @param array $checks The list of all checks (by-ref parameter!)
*/
public static function checkImagick(&$checks)
{
$imagick = false;
$gif = false;
if (class_exists('Imagick')) {
$imagick = true;
$supported = Image::supportedTypes();
if (array_key_exists('image/gif', $supported)) {
$gif = true;
}
}
if ($imagick == false) {
self::addCheck($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
} else {
self::addCheck($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
if ($imagick) {
self::addCheck($checks, L10n::t('ImageMagick supports GIF'), $gif, false, "");
}
}
}
/**
* Installs the Database structure
*
* @return string A possible error
*/
public static function installDatabaseStructure()
{
$errors = DBStructure::update(false, true, true);
return $errors;
}
}
+171 -156
View File
@@ -1,7 +1,9 @@
<?php
/**
* @file src/Core/Theme.php
*/
namespace Friendica\Core;
use Friendica\Core\System;
@@ -13,177 +15,190 @@ require_once 'boot.php';
*/
class Theme
{
/**
* @brief Parse theme comment in search of theme infos.
*
* like
* \code
* ..* Name: My Theme
* * Description: My Cool Theme
* . * Version: 1.2.3
* * Author: John <profile url>
* * Maintainer: Jane <profile url>
* *
* \endcode
* @param string $theme the name of the theme
* @return array
*/
/**
* @brief Parse theme comment in search of theme infos.
*
* like
* \code
* ..* Name: My Theme
* * Description: My Cool Theme
* . * Version: 1.2.3
* * Author: John <profile url>
* * Maintainer: Jane <profile url>
* *
* \endcode
* @param string $theme the name of the theme
* @return array
*/
public static function getInfo($theme)
{
$info = [
'name' => $theme,
'description' => "",
'author' => [],
'maintainer' => [],
'version' => "",
'credits' => "",
'experimental' => file_exists("view/theme/$theme/experimental"),
'unsupported' => file_exists("view/theme/$theme/unsupported")
];
public static function getInfo($theme)
{
$info=[
'name' => $theme,
'description' => "",
'author' => [],
'maintainer' => [],
'version' => "",
'credits' => "",
'experimental' => false,
'unsupported' => false
];
if (!is_file("view/theme/$theme/theme.php")) {
return $info;
}
if (file_exists("view/theme/$theme/experimental"))
$info['experimental'] = true;
if (file_exists("view/theme/$theme/unsupported"))
$info['unsupported'] = true;
$a = get_app();
$stamp1 = microtime(true);
$theme_file = file_get_contents("view/theme/$theme/theme.php");
$a->save_timestamp($stamp1, "file");
if (!is_file("view/theme/$theme/theme.php")) return $info;
$result = preg_match("|/\*.*\*/|msU", $theme_file, $matches);
$a = get_app();
$stamp1 = microtime(true);
$f = file_get_contents("view/theme/$theme/theme.php");
$a->save_timestamp($stamp1, "file");
if ($result) {
$comment_lines = explode("\n", $matches[0]);
foreach ($comment_lines as $comment_line) {
$comment_line = trim($comment_line, "\t\n\r */");
if ($comment_line != "") {
list($key, $value) = array_map("trim", explode(":", $comment_line, 2));
$key = strtolower($key);
if ($key == "author") {
$result = preg_match("|([^<]+)<([^>]+)>|", $value, $matches);
if ($result) {
$info['author'][] = ['name' => $matches[1], 'link' => $matches[2]];
} else {
$info['author'][] = ['name' => $value];
}
} elseif ($key == "maintainer") {
$result = preg_match("|([^<]+)<([^>]+)>|", $value, $matches);
if ($result) {
$info['maintainer'][] = ['name' => $matches[1], 'link' => $matches[2]];
} else {
$info['maintainer'][] = ['name' => $value];
}
} elseif (array_key_exists($key, $info)) {
$info[$key] = $value;
}
}
}
}
return $info;
}
$r = preg_match("|/\*.*\*/|msU", $f, $m);
/**
* @brief Returns the theme's screenshot.
*
* The screenshot is expected as view/theme/$theme/screenshot.[png|jpg].
*
* @param sring $theme The name of the theme
* @return string
*/
public static function getScreenshot($theme)
{
$exts = ['.png', '.jpg'];
foreach ($exts as $ext) {
if (file_exists('view/theme/' . $theme . '/screenshot' . $ext)) {
return(System::baseUrl() . '/view/theme/' . $theme . '/screenshot' . $ext);
}
}
return(System::baseUrl() . '/images/blank.png');
}
if ($r) {
$ll = explode("\n", $m[0]);
foreach ( $ll as $l ) {
$l = trim($l,"\t\n\r */");
if ($l != "") {
list($k, $v) = array_map("trim", explode(":", $l, 2));
$k= strtolower($k);
if ($k == "author") {
// install and uninstall theme
public static function uninstall($theme)
{
logger("Addons: uninstalling theme " . $theme);
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['author'][] = ['name'=>$m[1], 'link'=>$m[2]];
} else {
$info['author'][] = ['name'=>$v];
}
} elseif ($k == "maintainer") {
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['maintainer'][] = ['name'=>$m[1], 'link'=>$m[2]];
} else {
$info['maintainer'][] = ['name'=>$v];
}
} else {
if (array_key_exists($k, $info)) {
$info[$k] = $v;
}
}
}
}
}
return $info;
}
include_once "view/theme/$theme/theme.php";
if (function_exists("{$theme}_uninstall")) {
$func = "{$theme}_uninstall";
$func();
}
}
/**
* @brief Returns the theme's screenshot.
*
* The screenshot is expected as view/theme/$theme/screenshot.[png|jpg].
*
* @param sring $theme The name of the theme
* @return string
*/
public static function getScreenshot($theme)
{
$exts = ['.png','.jpg'];
foreach ($exts as $ext) {
if (file_exists('view/theme/' . $theme . '/screenshot' . $ext)) {
return(System::baseUrl() . '/view/theme/' . $theme . '/screenshot' . $ext);
}
}
return(System::baseUrl() . '/images/blank.png');
}
public static function install($theme)
{
// silently fail if theme was removed
// install and uninstall theme
public static function uninstall($theme)
{
logger("Addons: uninstalling theme " . $theme);
if (!file_exists("view/theme/$theme/theme.php")) {
return false;
}
include_once("view/theme/$theme/theme.php");
if (function_exists("{$theme}_uninstall")) {
$func = "{$theme}_uninstall";
$func();
}
}
logger("Addons: installing theme $theme");
public static function install($theme)
{
// silently fail if theme was removed
include_once "view/theme/$theme/theme.php";
if (! file_exists("view/theme/$theme/theme.php")) {
return false;
}
if (function_exists("{$theme}_install")) {
$func = "{$theme}_install";
$func();
return true;
} else {
logger("Addons: FAILED installing theme $theme");
return false;
}
}
logger("Addons: installing theme $theme");
/**
* @brief Get the full path to relevant theme files by filename
*
* This function search in the theme directory (and if not present in global theme directory)
* if there is a directory with the file extension and for a file with the given
* filename.
*
* @param string $file Filename
* @param string $root Full root path
* @return string Path to the file or empty string if the file isn't found
*/
public static function getPathForFile($file, $root = '')
{
$file = basename($file);
include_once("view/theme/$theme/theme.php");
// Make sure $root ends with a slash / if it's not blank
if ($root !== '' && $root[strlen($root) - 1] !== '/') {
$root = $root . '/';
}
$theme_info = get_app()->theme_info;
if (is_array($theme_info) && array_key_exists('extends', $theme_info)) {
$parent = $theme_info['extends'];
} else {
$parent = 'NOPATH';
}
$theme = get_app()->getCurrentTheme();
$thname = $theme;
$ext = substr($file, strrpos($file, '.') + 1);
$paths = [
"{$root}view/theme/$thname/$ext/$file",
"{$root}view/theme/$parent/$ext/$file",
"{$root}view/$ext/$file",
];
foreach ($paths as $p) {
// strpos() is faster than strstr when checking if one string is in another (http://php.net/manual/en/function.strstr.php)
if (strpos($p, 'NOPATH') !== false) {
continue;
} elseif (file_exists($p)) {
return $p;
}
}
return '';
}
if (function_exists("{$theme}_install")) {
$func = "{$theme}_install";
$func();
return true;
} else {
logger("Addons: FAILED installing theme $theme");
return false;
}
/**
* @brief Return relative path to theme stylesheet file
*
* Provide a sane default if nothing is chosen or the specified theme does not exist.
*
* @param string $theme Theme name
*
* @return string
*/
public static function getStylesheetPath($theme)
{
$a = get_app();
}
$opts = (($a->profile_uid) ? '?f=&puid=' . $a->profile_uid : '');
if (file_exists('view/theme/' . $theme . '/style.php')) {
return 'view/theme/' . $theme . '/style.pcss' . $opts;
}
/**
* @brief Get the full path to relevant theme files by filename
*
* This function search in the theme directory (and if not present in global theme directory)
* if there is a directory with the file extension and for a file with the given
* filename.
*
* @param string $file Filename
* @param string $root Full root path
* @return string Path to the file or empty string if the file isn't found
*/
public static function getPathForFile($file, $root = '')
{
$file = basename($file);
// Make sure $root ends with a slash / if it's not blank
if ($root !== '' && $root[strlen($root)-1] !== '/') {
$root = $root . '/';
}
$theme_info = get_app()->theme_info;
if (is_array($theme_info) && array_key_exists('extends',$theme_info)) {
$parent = $theme_info['extends'];
} else {
$parent = 'NOPATH';
}
$theme = current_theme();
$thname = $theme;
$ext = substr($file,strrpos($file,'.')+1);
$paths = [
"{$root}view/theme/$thname/$ext/$file",
"{$root}view/theme/$parent/$ext/$file",
"{$root}view/$ext/$file",
];
foreach ($paths as $p) {
// strpos() is faster than strstr when checking if one string is in another (http://php.net/manual/en/function.strstr.php)
if (strpos($p,'NOPATH') !== false) {
continue;
} elseif (file_exists($p)) {
return $p;
}
}
return '';
}
return 'view/theme/' . $theme . '/style.css';
}
}
+50 -8
View File
@@ -862,12 +862,32 @@ class Item extends BaseObject
}
unset($item['id']);
unset($item['parent']);
unset($item['mention']);
unset($item['wall']);
unset($item['origin']);
unset($item['starred']);
unset($item['rendered-hash']);
unset($item['rendered-html']);
$condition = ["`nurl` IN (SELECT `nurl` FROM `contact` WHERE `id` = ?) AND `uid` != 0 AND NOT `blocked` AND NOT `readonly` AND `rel` IN (?, ?)",
$users = [];
$condition = ["`nurl` IN (SELECT `nurl` FROM `contact` WHERE `id` = ?) AND `uid` != 0 AND NOT `blocked` AND `rel` IN (?, ?)",
$parent['owner-id'], CONTACT_IS_SHARING, CONTACT_IS_FRIEND];
$contacts = dba::select('contact', ['uid'], $condition);
while ($contact = dba::fetch($contacts)) {
self::storeForUser($itemid, $item, $contact['uid']);
$users[$contact['uid']] = $contact['uid'];
}
if ($item['uri'] != $item['parent-uri']) {
$parents = dba::select('item', ['uid'], ["`uri` = ? AND `uid` != 0", $item['parent-uri']]);
while ($parent = dba::fetch($parents)) {
$users[$parent['uid']] = $parent['uid'];
}
}
foreach ($users as $uid) {
self::storeForUser($itemid, $item, $uid);
}
}
@@ -955,10 +975,15 @@ class Item extends BaseObject
if (!dba::exists('item', ['uri' => $item['uri'], 'uid' => 0])) {
// Preparing public shadow (removing user specific data)
unset($item['id']);
$item['uid'] = 0;
$item['origin'] = 0;
$item['wall'] = 0;
unset($item['id']);
unset($item['parent']);
unset($item['wall']);
unset($item['mention']);
unset($item['origin']);
unset($item['starred']);
unset($item['rendered-hash']);
unset($item['rendered-html']);
if ($item['uri'] == $item['parent-uri']) {
$item['contact-id'] = Contact::getIdForURL($item['owner-link']);
} else {
@@ -1012,11 +1037,20 @@ class Item extends BaseObject
return;
}
// Save "origin" and "parent" state
$origin = $item['origin'];
$parent = $item['parent'];
// Preparing public shadow (removing user specific data)
unset($item['id']);
$item['uid'] = 0;
$item['origin'] = 0;
$item['wall'] = 0;
unset($item['id']);
unset($item['parent']);
unset($item['wall']);
unset($item['mention']);
unset($item['origin']);
unset($item['starred']);
unset($item['rendered-hash']);
unset($item['rendered-html']);
$item['contact-id'] = Contact::getIdForURL($item['author-link']);
if (in_array($item['type'], ["net-comment", "wall-comment"])) {
@@ -1028,6 +1062,14 @@ class Item extends BaseObject
$public_shadow = self::insert($item, false, false, true);
logger("Stored public shadow for comment ".$item['uri']." under id ".$public_shadow, LOGGER_DEBUG);
// If this was a comment to a Diaspora post we don't get our comment back.
// This means that we have to distribute the comment by ourselves.
if ($origin) {
if (dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) {
self::distribute($public_shadow);
}
}
}
/**
+2 -2
View File
@@ -152,7 +152,7 @@ class Profile
$a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one
$theme_info_file = 'view/theme/' . current_theme() . '/theme.php';
$theme_info_file = 'view/theme/' . $a->getCurrentTheme() . '/theme.php';
if (file_exists($theme_info_file)) {
require_once $theme_info_file;
}
@@ -950,7 +950,7 @@ class Profile
];
}
if ((!$is_owner) && ((count($a->profile)) || (!$a->profile['hide-friends']))) {
if (!$is_owner && empty($a->profile['hide-friends'])) {
$tabs[] = [
'label' => L10n::t('Contacts'),
'url' => System::baseUrl() . '/viewcontacts/' . $nickname,
+19 -21
View File
@@ -1405,25 +1405,27 @@ class DFRN
{
$a = get_app();
if (empty($contact['addr'])) {
logger('Empty contact handle for ' . $contact['id'] . ' - ' . $contact['url'] . ' - trying to update it.');
if (Contact::updateFromProbe($contact['id'])) {
$new_contact = dba::selectFirst('contact', ['addr'], ['id' => $contact['id']]);
$contact['addr'] = $new_contact['addr'];
}
if (!$public_batch) {
if (empty($contact['addr'])) {
logger('Unable to find contact handle for ' . $contact['id'] . ' - ' . $contact['url']);
Contact::markForArchival($contact);
return -21;
}
}
logger('Empty contact handle for ' . $contact['id'] . ' - ' . $contact['url'] . ' - trying to update it.');
if (Contact::updateFromProbe($contact['id'])) {
$new_contact = dba::selectFirst('contact', ['addr'], ['id' => $contact['id']]);
$contact['addr'] = $new_contact['addr'];
}
$fcontact = Diaspora::personByHandle($contact['addr']);
if (empty($fcontact)) {
logger('Unable to find contact details for ' . $contact['id'] . ' - ' . $contact['addr']);
Contact::markForArchival($contact);
return -22;
if (empty($contact['addr'])) {
logger('Unable to find contact handle for ' . $contact['id'] . ' - ' . $contact['url']);
Contact::markForArchival($contact);
return -21;
}
}
$fcontact = Diaspora::personByHandle($contact['addr']);
if (empty($fcontact)) {
logger('Unable to find contact details for ' . $contact['id'] . ' - ' . $contact['addr']);
Contact::markForArchival($contact);
return -22;
}
}
$envelope = Diaspora::buildMessage($atom, $owner, $contact, $owner['uprvkey'], $fcontact['pubkey'], $public_batch);
@@ -2797,10 +2799,6 @@ class DFRN
return true;
}
} else { // $entrytype == DFRN_TOP_LEVEL
if ($importer["readonly"]) {
logger('ignoring read-only contact '.$importer["id"]);
return;
}
if (($importer["uid"] == 0) && ($importer["importer_uid"] != 0)) {
logger("Contact ".$importer["id"]." isn't known to user ".$importer["importer_uid"].". The post will be ignored.", LOGGER_DEBUG);
return;
+34 -16
View File
@@ -596,9 +596,9 @@ class Diaspora
}
$importer = ["uid" => 0, "page-flags" => PAGE_FREELOVE];
$message_id = self::dispatch($importer, $msg, $fields);
$success = self::dispatch($importer, $msg, $fields);
return $message_id;
return $success;
}
/**
@@ -832,6 +832,10 @@ class Diaspora
if (isset($parent_author_signature)) {
$key = self::key($msg["author"]);
if (empty($key)) {
logger("No key found for parent author ".$msg["author"], LOGGER_DEBUG);
return false;
}
if (!Crypto::rsaVerify($signed_data, $parent_author_signature, $key, "sha256")) {
logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
@@ -840,6 +844,10 @@ class Diaspora
}
$key = self::key($fields->author);
if (empty($key)) {
logger("No key found for author ".$fields->author, LOGGER_DEBUG);
return false;
}
if (!Crypto::rsaVerify($signed_data, $author_signature, $key, "sha256")) {
logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
@@ -1143,7 +1151,7 @@ class Diaspora
//}
// We don't seem to like that person
if ($contact["blocked"] || $contact["readonly"]) {
if ($contact["blocked"]) {
// Maybe blocked, don't accept.
return false;
// We are following this person?
@@ -2721,10 +2729,15 @@ class Diaspora
*/
public static function originalItem($guid, $orig_author)
{
if (empty($guid)) {
logger('Empty guid. Quitting.');
return false;
}
// Do we already have this item?
$fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
'author-name', 'author-link', 'author-avatar'];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
$item = dba::selectfirst('item', $fields, $condition);
if (DBM::is_result($item)) {
@@ -2734,7 +2747,7 @@ class Diaspora
// Then refetch the content, if it is a reshare from a reshare.
// If it is a reshared post from another network then reformat to avoid display problems with two share elements
if (self::isReshare($item["body"], true)) {
$r = [];
$item = [];
} elseif (self::isReshare($item["body"], false) || strstr($item["body"], "[share")) {
$item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
@@ -2749,21 +2762,26 @@ class Diaspora
}
}
if (!DBM::is_result($r)) {
$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server);
$item_id = self::storeByGuid($guid, $server);
if (!$item_id) {
$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("2nd try: reshared message ".$guid." will be fetched without SLL from the server ".$server);
$item_id = self::storeByGuid($guid, $server);
if (!DBM::is_result($item)) {
if (empty($orig_author)) {
logger('Empty author for guid ' . $guid . '. Quitting.');
return false;
}
if ($item_id) {
$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server);
$stored = self::storeByGuid($guid, $server);
if (!$stored) {
$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("2nd try: reshared message ".$guid." will be fetched without SSL from the server ".$server);
$stored = self::storeByGuid($guid, $server);
}
if ($stored) {
$fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
'author-name', 'author-link', 'author-avatar'];
$condition = ['id' => $item_id, 'visible' => true, 'deleted' => false];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
$item = dba::selectfirst('item', $fields, $condition);
if (DBM::is_result($item)) {
+1 -1
View File
@@ -22,7 +22,7 @@ class FriendicaSmarty extends Smarty
parent::__construct();
$a = get_app();
$theme = current_theme();
$theme = $a->getCurrentTheme();
// setTemplateDir can be set to an array, which Smarty will parse in order.
// The order is thus very important here
+1 -1
View File
@@ -62,7 +62,7 @@ class FriendicaSmartyEngine implements ITemplateEngine
$root = $root . '/';
}
$theme = current_theme();
$theme = $a->getCurrentTheme();
$filename = $template::SMARTY3_TEMPLATE_FOLDER . '/' . $file;
if (file_exists("{$root}view/theme/$theme/$filename")) {
+24 -3
View File
@@ -36,7 +36,30 @@ class Network
*/
public static function fetchUrl($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = 0)
{
$ret = self::curl(
$ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar);
return $ret['body'];
}
/**
* @brief Curl wrapper with array of return values.
*
* Inner workings and parameters are the same as @ref fetchUrl but returns an array with
* all the information collected during the fetch.
*
* @param string $url URL to fetch
* @param boolean $binary default false
* TRUE if asked to return binary results (file download)
* @param integer $redirects The recursion counter for internal use - default 0
* @param integer $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
*
* @return array With all relevant information, 'body' contains the actual fetched content.
*/
public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = 0)
{
return self::curl(
$url,
$binary,
$redirects,
@@ -45,8 +68,6 @@ class Network
'cookiejar'=>$cookiejar
]
);
return($ret['body']);
}
/**
+328 -395
View File
@@ -4,6 +4,7 @@
*/
namespace Friendica\Worker;
use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\System;
@@ -19,98 +20,67 @@ use dba;
require_once 'include/items.php';
/// @todo This is some ugly code that needs to be split into several methods
class Delivery extends BaseObject
{
const MAIL = 'mail';
const SUGGESTION = 'suggest';
const RELOCATION = 'relocate';
const DELETION = 'drop';
const POST = 'wall-new';
const COMMENT = 'comment-new';
class Delivery {
public static function execute($cmd, $item_id, $contact_id) {
global $a;
public static function execute($cmd, $item_id, $contact_id)
{
logger('Invoked: ' . $cmd . ': ' . $item_id . ' to ' . $contact_id, LOGGER_DEBUG);
logger('delivery: invoked: '.$cmd.': '.$item_id.' to '.$contact_id, LOGGER_DEBUG);
$mail = false;
$fsuggest = false;
$relocate = false;
$top_level = false;
$recipients = [];
$followup = false;
$public_message = false;
$normal_mode = true;
$item = null;
$recipients[] = $contact_id;
if ($cmd === 'mail') {
$normal_mode = false;
$mail = true;
$message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if (!count($message)) {
if ($cmd == self::MAIL) {
$target_item = dba::selectFirst('mail', [], ['id' => $item_id]);
if (!DBM::is_result($message)) {
return;
}
$uid = $message[0]['uid'];
$recipients[] = $message[0]['contact-id'];
$item = $message[0];
} elseif ($cmd === 'suggest') {
$normal_mode = false;
$fsuggest = true;
$suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if (!count($suggest)) {
$uid = $target_item['uid'];
} elseif ($cmd == self::SUGGESTION) {
$target_item = dba::selectFirst('fsuggest', [], ['id' => $item_id]);
if (!DBM::is_result($message)) {
return;
}
$uid = $suggest[0]['uid'];
$recipients[] = $suggest[0]['cid'];
$item = $suggest[0];
} elseif ($cmd === 'relocate') {
$normal_mode = false;
$relocate = true;
$uid = $target_item['uid'];
} elseif ($cmd == self::RELOCATION) {
$uid = $item_id;
} else {
// find ancestors
$target_item = dba::fetch_first("SELECT `item`.*, `contact`.`uid` AS `cuid` FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`id` = ? AND `visible` AND NOT `moderated`", $item_id);
if (!DBM::is_result($target_item) || !intval($target_item['parent'])) {
$item = dba::selectFirst('item', ['parent'], ['id' => $item_id]);
if (!DBM::is_result($item) || empty($item['parent'])) {
return;
}
$parent_id = intval($item['parent']);
$parent_id = intval($target_item['parent']);
$uid = $target_item['cuid'];
$updated = $target_item['edited'];
$items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC",
intval($parent_id)
);
if (!count($items)) {
return;
}
$icontacts = null;
$contacts_arr = [];
foreach ($items as $item) {
if (!in_array($item['contact-id'],$contacts_arr)) {
$contacts_arr[] = intval($item['contact-id']);
$itemdata = dba::p("SELECT `item`.*, `contact`.`uid` AS `cuid`,
`sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`
WHERE `item`.`id` IN (?, ?) AND `visible` AND NOT `moderated`
ORDER BY `item`.`id`",
$item_id, $parent_id);
$items = [];
while ($item = dba::fetch($itemdata)) {
if ($item['id'] == $parent_id) {
$parent = $item;
}
if ($item['id'] == $item_id) {
$target_item = $item;
}
$items[] = $item;
}
if (count($contacts_arr)) {
$str_contacts = implode(',',$contacts_arr);
$icontacts = q("SELECT * FROM `contact`
WHERE `id` IN ( $str_contacts ) "
);
}
if ( !($icontacts && count($icontacts))) {
return;
}
dba::close($itemdata);
$uid = $target_item['cuid'];
// avoid race condition with deleting entries
if ($items[0]['deleted']) {
foreach ($items as $item) {
$item['deleted'] = 1;
@@ -120,24 +90,10 @@ class Delivery {
// When commenting too fast after delivery, a post wasn't recognized as top level post.
// The count then showed more than one entry. The additional check should help.
// The check for the "count" should be superfluous, but I'm not totally sure by now, so we keep it.
if ((($items[0]['id'] == $item_id) || (count($items) == 1)) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
logger('delivery: top level post');
if ((($parent['id'] == $item_id) || (count($items) == 1)) && ($parent['uri'] === $parent['parent-uri'])) {
logger('Top level post');
$top_level = true;
}
}
$owner = User::getOwnerDataById($uid);
if (!$owner) {
return;
}
// We don't treat Forum posts as "wall-to-wall" to be able to post them via Diaspora
$walltowall = $top_level && ($owner['id'] != $items[0]['contact-id']) & ($owner['account-type'] != ACCOUNT_TYPE_COMMUNITY);
$public_message = true;
if (!$mail && !$fsuggest && !$relocate) {
$parent = $items[0];
// This is IMPORTANT!!!!
@@ -147,9 +103,9 @@ class Delivery {
// if $parent['wall'] == 1 we will already have the parent message in our array
// and we will relay the whole lot.
$localhost = $a->get_hostname();
if (strpos($localhost,':')) {
$localhost = substr($localhost,0,strpos($localhost,':'));
$localhost = self::getApp()->get_hostname();
if (strpos($localhost, ':')) {
$localhost = substr($localhost, 0, strpos($localhost, ':'));
}
/**
*
@@ -159,26 +115,24 @@ class Delivery {
*
*/
$relay_to_owner = false;
if (!$top_level && ($parent['wall'] == 0) && stristr($target_item['uri'], $localhost)) {
$relay_to_owner = true;
}
if ($relay_to_owner) {
logger('followup '.$target_item["guid"], LOGGER_DEBUG);
logger('Followup ' . $target_item["guid"], LOGGER_DEBUG);
// local followup to remote post
$followup = true;
}
if (strlen($parent['allow_cid'])
|| strlen($parent['allow_gid'])
|| strlen($parent['deny_cid'])
|| strlen($parent['deny_gid'])
|| $parent["private"]) {
$public_message = false; // private recipients, not public
if (empty($parent['allow_cid'])
&& empty($parent['allow_gid'])
&& empty($parent['deny_cid'])
&& empty($parent['deny_gid'])
&& !$parent["private"]) {
$public_message = true;
}
}
$owner = User::getOwnerDataById($uid);
if (!DBM::is_result($owner)) {
return;
}
// We don't deliver our items to blocked or pending contacts, and not to ourselves either
@@ -189,146 +143,22 @@ class Delivery {
return;
}
$deliver_status = 0;
// Transmit via Diaspora if not possible via Friendica
if (($item['uid'] == 0) && ($contact['network'] == NETWORK_DFRN)) {
// Transmit via Diaspora if the thread had started as Diaspora post
// This is done since the uri wouldn't match (Diaspora doesn't transmit it)
if (isset($parent) && ($parent['network'] == NETWORK_DIASPORA) && ($contact['network'] == NETWORK_DFRN)) {
$contact['network'] = NETWORK_DIASPORA;
}
logger("main delivery by delivery: followup=$followup mail=$mail fsuggest=$fsuggest relocate=$relocate - network ".$contact['network']);
logger("Delivering " . $cmd . " followup=$followup - via network " . $contact['network']);
switch ($contact['network']) {
case NETWORK_DFRN:
logger('notifier: '.$target_item["guid"].' dfrndelivery: '.$contact['name']);
if ($mail) {
$item['body'] = Item::fixPrivatePhotos($item['body'], $owner['uid'], null, $item['contact-id']);
$atom = DFRN::mail($item, $owner);
} elseif ($fsuggest) {
$atom = DFRN::fsuggest($item, $owner);
dba::delete('fsuggest', ['id' => $item['id']]);
} elseif ($relocate) {
$atom = DFRN::relocate($owner, $uid);
} elseif ($followup) {
$msgitems = [];
foreach ($items as $item) { // there is only one item
if (!$item['parent']) {
return;
}
if ($item['id'] == $item_id) {
logger('followup: item: '. print_r($item,true), LOGGER_DATA);
$msgitems[] = $item;
}
}
$atom = DFRN::entries($msgitems,$owner);
} else {
$msgitems = [];
foreach ($items as $item) {
if (!$item['parent']) {
return;
}
// private emails may be in included in public conversations. Filter them.
if ($public_message && $item['private']) {
return;
}
$item_contact = self::getItemContact($item,$icontacts);
if (!$item_contact) {
return;
}
if ($normal_mode) {
// Only add the parent when we don't delete other items.
if ($item_id == $item['id'] || (($item['id'] == $item['parent']) && ($cmd != 'drop'))) {
$item["entry:comment-allow"] = true;
$item["entry:cid"] = (($top_level) ? $contact['id'] : 0);
$msgitems[] = $item;
}
} else {
$item["entry:comment-allow"] = true;
$msgitems[] = $item;
}
}
$atom = DFRN::entries($msgitems,$owner);
}
logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG);
logger('notifier: '.$atom, LOGGER_DATA);
$basepath = implode('/', array_slice(explode('/',$contact['url']),0,3));
// perform local delivery if we are on the same site
if (link_compare($basepath,System::baseUrl())) {
$nickname = basename($contact['url']);
if ($contact['issued-id']) {
$sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id']));
} else {
$sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id']));
}
$x = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`,
`contact`.`pubkey` AS `cpubkey`,
`contact`.`prvkey` AS `cprvkey`,
`contact`.`thumb` AS `thumb`,
`contact`.`url` as `url`,
`contact`.`name` as `senderName`,
`user`.*
FROM `contact`
INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `contact`.`network` = '%s' AND `user`.`nickname` = '%s'
$sql_extra
AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 LIMIT 1",
dbesc(NETWORK_DFRN),
dbesc($nickname)
);
if ($x && count($x)) {
$write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
dba::update('contact', ['writable' => true], ['id' => $x[0]['id']]);
$x[0]['writable'] = 1;
}
$ssl_policy = Config::get('system','ssl_policy');
$x[0] = Contact::updateSslPolicy($x[0], $ssl_policy);
// If we are setup as a soapbox we aren't accepting top level posts from this person
if (($x[0]['page-flags'] == PAGE_SOAPBOX) && $top_level) {
break;
}
logger('mod-delivery: local delivery');
DFRN::import($atom, $x[0]);
break;
}
}
if (!Queue::wasDelayed($contact['id'])) {
$deliver_status = DFRN::deliver($owner, $contact, $atom);
} else {
$deliver_status = -1;
}
logger('notifier: dfrn_delivery to '.$contact["url"].' with guid '.$target_item["guid"].' returns '.$deliver_status);
if ($deliver_status < 0) {
logger('notifier: delivery failed: queuing message');
Queue::add($contact['id'], NETWORK_DFRN, $atom, false, $target_item['guid']);
}
if (($deliver_status >= 200) && ($deliver_status <= 299)) {
// We successfully delivered a message, the contact is alive
Contact::unmarkForArchival($contact);
} else {
// The message could not be delivered. We mark the contact as "dead"
Contact::markForArchival($contact);
}
self::deliverDFRN($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);
break;
case NETWORK_DIASPORA:
self::deliverDiaspora($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);
break;
case NETWORK_OSTATUS:
@@ -345,156 +175,7 @@ class Delivery {
break;
case NETWORK_MAIL:
if (Config::get('system','dfrn_only')) {
break;
}
// WARNING: does not currently convert to RFC2047 header encodings, etc.
$addr = $contact['addr'];
if (!strlen($addr)) {
break;
}
if ($cmd === 'wall-new' || $cmd === 'comment-new') {
$it = null;
if ($cmd === 'wall-new') {
$it = $items[0];
} else {
$r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if (DBM::is_result($r)) {
$it = $r[0];
}
}
if (!$it) {
break;
}
$local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if (!count($local_user)) {
break;
}
$reply_to = '';
$r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if ($r1 && $r1[0]['reply_to']) {
$reply_to = $r1[0]['reply_to'];
}
$subject = (($it['title']) ? Email::encodeHeader($it['title'],'UTF-8') : L10n::t("\x28no subject\x29")) ;
// only expose our real email address to true friends
if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
if ($reply_to) {
$headers = 'From: '.Email::encodeHeader($local_user[0]['username'],'UTF-8').' <'.$reply_to.'>'."\n";
$headers .= 'Sender: '.$local_user[0]['email']."\n";
} else {
$headers = 'From: '.Email::encodeHeader($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
}
} else {
$headers = 'From: '. Email::encodeHeader($local_user[0]['username'], 'UTF-8') . ' <noreply@' . $a->get_hostname() . '>' . "\n";
}
//if ($reply_to)
// $headers .= 'Reply-to: '.$reply_to . "\n";
$headers .= 'Message-Id: <'. Email::iri2msgid($it['uri']).'>'. "\n";
//logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG);
//logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG);
//logger("Mail: Data: ".print_r($it, true), LOGGER_DATA);
if ($it['uri'] !== $it['parent-uri']) {
$headers .= "References: <".Email::iri2msgid($it["parent-uri"]).">";
// If Threading is enabled, write down the correct parent
if (($it["thr-parent"] != "") && ($it["thr-parent"] != $it["parent-uri"])) {
$headers .= " <".Email::iri2msgid($it["thr-parent"]).">";
}
$headers .= "\n";
if (!$it['title']) {
$r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($it['parent-uri']),
intval($uid));
if (DBM::is_result($r) && ($r[0]['title'] != '')) {
$subject = $r[0]['title'];
} else {
$r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($it['parent-uri']),
intval($uid));
if (DBM::is_result($r) && ($r[0]['title'] != '')) {
$subject = $r[0]['title'];
}
}
}
if (strncasecmp($subject,'RE:',3)) {
$subject = 'Re: '.$subject;
}
}
Email::send($addr, $subject, $headers, $it);
}
break;
case NETWORK_DIASPORA:
if ($public_message) {
$loc = 'public batch '.$contact['batch'];
} else {
$loc = $contact['name'];
}
logger('delivery: diaspora batch deliver: '.$loc);
if (Config::get('system','dfrn_only') || !Config::get('system','diaspora_enabled')) {
break;
}
if ($mail) {
Diaspora::sendMail($item,$owner,$contact);
break;
}
if (!$normal_mode) {
break;
}
if (!$contact['pubkey'] && !$public_message) {
break;
}
if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
// top-level retraction
logger('diaspora retract: '.$loc);
Diaspora::sendRetraction($target_item,$owner,$contact,$public_message);
break;
} elseif ($relocate) {
Diaspora::sendAccountMigration($owner, $contact, $uid);
break;
} elseif ($followup) {
// send comments and likes to owner to relay
logger('diaspora followup: '.$loc);
Diaspora::sendFollowup($target_item,$owner,$contact,$public_message);
break;
} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
// we are the relay - send comments, likes and relayable_retractions to our conversants
logger('diaspora relay: '.$loc);
Diaspora::sendRelay($target_item,$owner,$contact,$public_message);
break;
} elseif ($top_level && !$walltowall) {
// currently no workable solution for sending walltowall
logger('diaspora status: '.$loc);
Diaspora::sendStatus($target_item,$owner,$contact,$public_message);
break;
}
logger('delivery: diaspora unknown mode: '.$contact['name']);
self::deliverMail($cmd, $contact, $owner, $target_item);
break;
default:
@@ -504,16 +185,268 @@ class Delivery {
return;
}
private static function getItemContact($item, $contacts)
/**
* @brief Deliver content via DFRN
*
* @param string $cmd Command
* @param array $contact Contact record of the receiver
* @param array $owner Owner record of the sender
* @param array $items Item record of the content and the parent
* @param array $target_item Item record of the content
* @param boolean $public_message Is the content public?
* @param boolean $top_level Is it a thread starter?
* @param boolean $followup Is it an answer to a remote post?
*/
private static function deliverDFRN($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup)
{
if (!count($contacts) || !is_array($item)) {
return false;
logger('Deliver ' . $target_item["guid"] . ' via DFRN to ' . $contact['addr']);
if ($cmd == self::MAIL) {
$item = $target_item;
$item['body'] = Item::fixPrivatePhotos($item['body'], $owner['uid'], null, $item['contact-id']);
$atom = DFRN::mail($item, $owner);
} elseif ($cmd == self::SUGGESTION) {
$item = $target_item;
$atom = DFRN::fsuggest($item, $owner);
dba::delete('fsuggest', ['id' => $item['id']]);
} elseif ($cmd == self::RELOCATION) {
$atom = DFRN::relocate($owner, $owner['uid']);
} elseif ($followup) {
$msgitems = [$target_item];
$atom = DFRN::entries($msgitems, $owner);
} else {
$msgitems = [];
foreach ($items as $item) {
// Only add the parent when we don't delete other items.
if (($target_item['id'] == $item['id']) || ($cmd != self::DELETION)) {
$item["entry:comment-allow"] = true;
$item["entry:cid"] = ($top_level ? $contact['id'] : 0);
$msgitems[] = $item;
}
}
$atom = DFRN::entries($msgitems, $owner);
}
foreach ($contacts as $contact) {
if ($contact['id'] == $item['contact-id']) {
return $contact;
logger('Notifier entry: ' . $contact["url"] . ' ' . $target_item["guid"] . ' entry: ' . $atom, LOGGER_DATA);
$basepath = implode('/', array_slice(explode('/', $contact['url']), 0, 3));
// perform local delivery if we are on the same site
if (link_compare($basepath, System::baseUrl())) {
$condition = ['nurl' => normalise_link($contact['url']), 'self' => true];
$target_self = dba::selectFirst('contact', ['uid'], $condition);
if (!DBM::is_result($target_self)) {
return;
}
$target_uid = $target_self['uid'];
// Check if the user has got this contact
$cid = Contact::getIdForURL($owner['url'], $target_uid);
if (!$cid) {
// Otherwise there should be a public contact
$cid = Contact::getIdForURL($owner['url']);
if (!$cid) {
return;
}
}
// We now have some contact, so we fetch it
$target_importer = dba::fetch_first("SELECT *, `name` as `senderName`
FROM `contact`
WHERE NOT `blocked` AND `id` = ? LIMIT 1",
$cid);
// This should never fail
if (!DBM::is_result($target_importer)) {
return;
}
// Set the user id. This is important if this is a public contact
$target_importer['importer_uid'] = $target_uid;
DFRN::import($atom, $target_importer);
return;
}
// We don't have a relationship with contacts on a public post.
// Se we transmit with the new method and via Diaspora as a fallback
if ($items[0]['uid'] == 0) {
// Transmit in public if it's a relay post
$public_dfrn = ($contact['contact-type'] == ACCOUNT_TYPE_RELAY);
$deliver_status = DFRN::transmit($owner, $contact, $atom, $public_dfrn);
if (($deliver_status < 200) || ($deliver_status > 299)) {
// Transmit via Diaspora if not possible via Friendica
self::deliverDiaspora($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);
return;
}
} else {
$deliver_status = DFRN::deliver($owner, $contact, $atom);
}
logger('Delivery to ' . $contact["url"] . ' with guid ' . $target_item["guid"] . ' returns ' . $deliver_status);
if ($deliver_status < 0) {
logger('Delivery failed: queuing message ' . $target_item["guid"] );
Queue::add($contact['id'], NETWORK_DFRN, $atom, false, $target_item['guid']);
}
if (($deliver_status >= 200) && ($deliver_status <= 299)) {
// We successfully delivered a message, the contact is alive
Contact::unmarkForArchival($contact);
} else {
// The message could not be delivered. We mark the contact as "dead"
Contact::markForArchival($contact);
}
}
/**
* @brief Deliver content via Diaspora
*
* @param string $cmd Command
* @param array $contact Contact record of the receiver
* @param array $owner Owner record of the sender
* @param array $items Item record of the content and the parent
* @param array $target_item Item record of the content
* @param boolean $public_message Is the content public?
* @param boolean $top_level Is it a thread starter?
* @param boolean $followup Is it an answer to a remote post?
*/
private static function deliverDiaspora($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup)
{
// We don't treat Forum posts as "wall-to-wall" to be able to post them via Diaspora
$walltowall = $top_level && ($owner['id'] != $items[0]['contact-id']) & ($owner['account-type'] != ACCOUNT_TYPE_COMMUNITY);
if ($public_message) {
$loc = 'public batch ' . $contact['batch'];
} else {
$loc = $contact['addr'];
}
logger('Deliver ' . $target_item["guid"] . ' via Diaspora to ' . $loc);
if (Config::get('system', 'dfrn_only') || !Config::get('system', 'diaspora_enabled')) {
return;
}
if ($cmd == self::MAIL) {
Diaspora::sendMail($target_item, $owner, $contact);
return;
}
if ($cmd == self::SUGGESTION) {
return;
}
if (!$contact['pubkey'] && !$public_message) {
return;
}
if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
// top-level retraction
logger('diaspora retract: ' . $loc);
Diaspora::sendRetraction($target_item, $owner, $contact, $public_message);
return;
} elseif ($cmd == self::RELOCATION) {
Diaspora::sendAccountMigration($owner, $contact, $owner['uid']);
return;
} elseif ($followup) {
// send comments and likes to owner to relay
logger('diaspora followup: ' . $loc);
Diaspora::sendFollowup($target_item, $owner, $contact, $public_message);
return;
} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
// we are the relay - send comments, likes and relayable_retractions to our conversants
logger('diaspora relay: ' . $loc);
Diaspora::sendRelay($target_item, $owner, $contact, $public_message);
return;
} elseif ($top_level && !$walltowall) {
// currently no workable solution for sending walltowall
logger('diaspora status: ' . $loc);
Diaspora::sendStatus($target_item, $owner, $contact, $public_message);
return;
}
logger('Unknown mode ' . $cmd . ' for ' . $loc);
}
/**
* @brief Deliver content via mail
*
* @param string $cmd Command
* @param array $contact Contact record of the receiver
* @param array $owner Owner record of the sender
* @param array $target_item Item record of the content
*/
private static function deliverMail($cmd, $contact, $owner, $target_item)
{
if (Config::get('system','dfrn_only')) {
return;
}
// WARNING: does not currently convert to RFC2047 header encodings, etc.
$addr = $contact['addr'];
if (!strlen($addr)) {
return;
}
if (!in_array($cmd, [self::POST, self::COMMENT])) {
return;
}
$local_user = dba::selectFirst('user', [], ['uid' => $owner['uid']]);
if (!DBM::is_result($local_user)) {
return;
}
logger('Deliver ' . $target_item["guid"] . ' via mail to ' . $contact['addr']);
$reply_to = '';
$mailacct = dba::selectFirst('mailacct', ['reply_to'], ['uid' => $owner['uid']]);
if (DBM::is_result($mailacct) && !empty($mailacct['reply_to'])) {
$reply_to = $mailacct['reply_to'];
}
$subject = ($target_item['title'] ? Email::encodeHeader($target_item['title'], 'UTF-8') : L10n::t("\x28no subject\x29"));
// only expose our real email address to true friends
if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
if ($reply_to) {
$headers = 'From: ' . Email::encodeHeader($local_user['username'],'UTF-8') . ' <' . $reply_to.'>' . "\n";
$headers .= 'Sender: ' . $local_user['email'] . "\n";
} else {
$headers = 'From: ' . Email::encodeHeader($local_user['username'],'UTF-8').' <' . $local_user['email'] . '>' . "\n";
}
} else {
$headers = 'From: '. Email::encodeHeader($local_user['username'], 'UTF-8') . ' <noreply@' . self::getApp()->get_hostname() . '>' . "\n";
}
$headers .= 'Message-Id: <' . Email::iri2msgid($target_item['uri']) . '>' . "\n";
if ($target_item['uri'] !== $target_item['parent-uri']) {
$headers .= "References: <" . Email::iri2msgid($target_item["parent-uri"]) . ">";
// If Threading is enabled, write down the correct parent
if (($target_item["thr-parent"] != "") && ($target_item["thr-parent"] != $target_item["parent-uri"])) {
$headers .= " <".Email::iri2msgid($target_item["thr-parent"]).">";
}
$headers .= "\n";
if (empty($target_item['title'])) {
$condition = ['uri' => $target_item['parent-uri'], 'uid' => $owner['uid']];
$title = dba::selectFirst('item', ['title'], $condition);
if (DBM::is_result($title) && ($title['title'] != '')) {
$subject = $title['title'];
} else {
$condition = ['parent-uri' => $target_item['parent-uri'], 'uid' => $owner['uid']];
$title = dba::selectFirst('item', ['title'], $condition);
if (DBM::is_result($title) && ($title['title'] != '')) {
$subject = $title['title'];
}
}
}
if (strncasecmp($subject, 'RE:', 3)) {
$subject = 'Re: ' . $subject;
}
}
return false;
Email::send($addr, $subject, $headers, $target_item);
}
}
+2 -2
View File
@@ -309,7 +309,7 @@ class OnePoll
// Are we allowed to import from this person?
if ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly']) {
if ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked']) {
// set the last-update so we don't keep polling
dba::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]);
return;
@@ -590,7 +590,7 @@ class OnePoll
}
$hubmode = 'subscribe';
if ($contact['network'] === NETWORK_DFRN || $contact['blocked'] || $contact['readonly']) {
if ($contact['network'] === NETWORK_DFRN || $contact['blocked']) {
$hubmode = 'unsubscribe';
}
+1 -1
View File
@@ -68,7 +68,7 @@ class PubSubPublish {
$rr['topic']),
"X-Hub-Signature: sha1=".$hmac_sig];
logger('POST '.print_r($headers, true)."\n".$params, LOGGER_DEBUG);
logger('POST '.print_r($headers, true)."\n".$params, LOGGER_DATA);
Network::post($rr['callback_url'], $params, $headers);
$ret = $a->get_curl_code();
+1 -1
View File
@@ -65,7 +65,7 @@ $a->config['system']['no_regfullname'] = true;
//$a->config['system']['block_local_dir'] = false;
// Location of the global directory
$a->config['system']['directory'] = 'http://dir.friendica.social';
$a->config['system']['directory'] = 'https://dir.friendica.social';
// turn on friendica's log
$a->config['system']['debugging'] = true;
+7547 -7517
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -32,6 +32,9 @@ td.help {
td.help blockquote {
margin-left: 60px;
}
.error_header {
margin-left: 60px;
}
input[type="submit"] {
margin: 2em 0;
}
+7605 -7576
View File
File diff suppressed because it is too large Load Diff
+1372 -1366
View File
File diff suppressed because it is too large Load Diff
+6529 -6527
View File
File diff suppressed because it is too large Load Diff
+1529 -1529
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -1,6 +1,8 @@
<div class="field checkbox" id="div_id_{{$field.0}}">
<label for="id_{{$field.0}}">{{$field.1}}</label>
<label id="id_{{$field.0}}_label" for="id_{{$field.0}}">{{$field.1}}</label>
<input type="hidden" name="{{$field.0}}" value="0">
<input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" aria-describedby="{{$field.0}}_tip" value="1" {{if $field.2}}checked="checked"{{/if}} {{if $field.4}}{{$field.4}}{{/if}}>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -13,6 +13,8 @@
{{foreach $field.4 as $opt=>$val}}<option value="{{$val|escape:'html'}}">{{$val}}</option>{{/foreach}}
</select>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -3,5 +3,7 @@
<div class='field custom'>
<label for='{{$field.0}}'>{{$field.1}}</label>
{{$field.2}}
<span class='field_help'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+2
View File
@@ -2,5 +2,7 @@
<div class='field input' id='wrapper_{{$field.0}}'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<input{{if $field.6 eq 'email'}} type='email'{{elseif $field.6 eq 'url'}} type='url'{{else}} type="text"{{/if}} name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}} aria-describedby='{{$field.0}}_tip'>
{{if $field.3}}
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{/if}}
</div>
+2
View File
@@ -3,5 +3,7 @@
<div class='field checkbox'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.3|escape:'html'}}" {{if $field.2}}checked="true"{{/if}} aria-describedby='{{$field.0}}_tip'>
{{if $field.4}}
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.4}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -2,5 +2,7 @@
<div class='field input openid' id='wrapper_{{$field.0}}'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<input name='{{$field.0}}' id='id_{{$field.0}}' type="text" value="{{$field.2|escape:'html'}}" aria-describedby='{{$field.0}}_tip'>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+2
View File
@@ -2,5 +2,7 @@
<div class='field password' id='wrapper_{{$field.0}}'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<input type='password' name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq 'autofocus'}} autofocus{{/if}} aria-describedby='{{$field.0}}_tip'>
{{if $field.3}}
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{/if}}
</div>
+2
View File
@@ -1,5 +1,7 @@
<div class='field radio'>
<label for='id_{{$field.0}}_{{$field.2}}'>{{$field.1}}</label>
<input type="radio" name='{{$field.0}}' id='id_{{$field.0}}_{{$field.2}}' value="{{$field.2|escape:'html'}}" {{if $field.4}}checked{{/if}} aria-describedby={{$field.0}}_{{$field.2}}_tip'>
{{if $field.3}}
<span class='field_help' role='tooltip' id='{{$field.0}}_{{$field.2}}_tip'>{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -3,5 +3,7 @@
<div class='field richtext'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<textarea name='{{$field.0}}' id='id_{{$field.0}}' class="fieldRichtext" aria-describedby='{{$field.0}}_tip'>{{$field.2}}</textarea>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -5,5 +5,7 @@
<select name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>
{{foreach $field.4 as $opt=>$val}}<option value="{{$opt|escape:'html'}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
</select>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -5,5 +5,7 @@
<select name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>
{{$field.4}}
</select>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -3,5 +3,7 @@
<div class='field textarea'>
<label for='id_{{$field.0}}'>{{$field.1}}</label>
<textarea name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>{{$field.2}}</textarea>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -5,6 +5,8 @@
<select name='{{$field.0}}' id='id_{{$field.0}}' {{if $field.5}}onchange="previewTheme(this);"{{/if}} aria-describedby='{{$field.0}}_tip'>
{{foreach $field.4 as $opt=>$val}}<option value="{{$opt|escape:'html'}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
</select>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
{{if $field.5}}<div id="theme-preview"></div>{{/if}}
</div>
+3 -1
View File
@@ -10,5 +10,7 @@
{{if $field.4}}{{$field.4.1}}{{else}}ON{{/if}}
</a>
</div>
<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
{{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3}}</span>
{{/if}}
</div>
+1 -1
View File
@@ -107,7 +107,7 @@ $a->config['system']['no_regfullname'] = true;
//$a->config['system']['block_local_dir'] = false;
// Location of the global directory
$a->config['system']['directory'] = 'http://dir.friendica.social';
$a->config['system']['directory'] = 'https://dir.friendica.social';
// Authentication cookie lifetime, in days
$a->config['system']['auth_cookie_lifetime'] = 7;
+7 -1
View File
@@ -16,7 +16,13 @@
{{/if}}
</td><td>{{if $check.required}}(required){{/if}}</td></tr>
{{if $check.help}}
<tr><td class="help" colspan="3"><blockquote>{{$check.help}}</blockquote></td></tr>
<tr><td class="help" colspan="3">
<blockquote>{{$check.help}}</blockquote>
{{if $check.error_msg}}
<div class="error_header"><b>{{$check.error_msg.head}}</br><a href="{{$check.error_msg.url}}">{{$check.error_msg.url}}</a></b></div>
<blockquote>{{$check.error_msg.msg}}</blockquote>
{{/if}}
</td></tr>
{{/if}}
{{/foreach}}
</table>
+12 -8
View File
@@ -4,11 +4,14 @@
<div id="login-group" role="group" aria-labelledby="login-head">
<input type="hidden" name="auth-params" value="login" />
<div id="login-head" class="sr-only">{{$login}}</div>
<h3 id="login-head" class="sr-only">{{$login}}</h3>
<div id="login_standard">
{{include file="field_input.tpl" field=$lname}}
{{include file="field_password.tpl" field=$lpassword}}
<div id="login-lost-password-link">
<a href="lostpass" title="{{$lostpass|escape:'html'}}" id="lost-password-link" >{{$lostlink}}</a>
</div>
</div>
{{if $openid}}
@@ -17,16 +20,11 @@
</div>
{{/if}}
{{include file="field_checkbox.tpl" field=$lremember}}
<div id="login-extra-links">
{{if $register}}<a href="register" title="{{$register.title|escape:'html'}}" id="register-link">{{$register.desc}}</a>{{/if}}
<a href="lostpass" title="{{$lostpass|escape:'html'}}" id="lost-password-link" >{{$lostlink}}</a>
</div>
<div id="login-submit-wrapper" >
<input type="submit" name="submit" id="login-submit-button" value="{{$login|escape:'html'}}" />
</div>
{{include file="field_checkbox.tpl" field=$lremember}}
{{foreach $hiddens as $k=>$v}}
<input type="hidden" name="{{$k}}" value="{{$v|escape:'html'}}" />
@@ -35,5 +33,11 @@
</div>
</form>
{{if $register}}
<div id="login-extra-links">
<h3 id="login-head" class="sr-only">{{$register.title|escape:'html'}}</h3>
<a href="register" title="{{$register.title|escape:'html'}}" id="register-link">{{$register.desc}}</a>
</div>
{{/if}}
<script type="text/javascript"> $(document).ready(function() { $("#id_{{$lname.0}}").focus();} );</script>
+4 -4
View File
@@ -37,11 +37,11 @@ Don't blame me too much for ugly code and hacks. Fix it ;-)
**Theme - Settings**
![Theme - Settings](https://github.com/rabuzarus/frio/blob/master/img/screenshots/screenshot-settings.png)
**Red schema**
![Red schema](https://github.com/rabuzarus/frio/blob/master/img/screenshots/screenshot-schema-red.png)
**Red scheme**
![Red scheme](https://github.com/rabuzarus/frio/blob/master/img/screenshots/screenshot-scheme-red.png)
**Love Music schema**
![Love Music schema](https://github.com/rabuzarus/frio/blob/master/img/screenshots/screenshot-schema-love-music.png)
**Love Music scheme**
![Love Music scheme](https://github.com/rabuzarus/frio/blob/master/img/screenshots/screenshot-scheme-love-music.png)
**frio on mobile**
+68 -62
View File
@@ -8,128 +8,134 @@ use Friendica\Core\System;
require_once 'view/theme/frio/php/Image.php';
function theme_post(App $a) {
function theme_post(App $a)
{
if (!local_user()) {
return;
}
if (isset($_POST['frio-settings-submit'])) {
PConfig::set(local_user(), 'frio', 'schema', $_POST["frio_schema"]);
PConfig::set(local_user(), 'frio', 'nav_bg', $_POST["frio_nav_bg"]);
PConfig::set(local_user(), 'frio', 'nav_icon_color', $_POST["frio_nav_icon_color"]);
PConfig::set(local_user(), 'frio', 'link_color', $_POST["frio_link_color"]);
PConfig::set(local_user(), 'frio', 'background_color', $_POST["frio_background_color"]);
PConfig::set(local_user(), 'frio', 'contentbg_transp', $_POST["frio_contentbg_transp"]);
PConfig::set(local_user(), 'frio', 'background_image', $_POST["frio_background_image"]);
PConfig::set(local_user(), 'frio', 'bg_image_option', $_POST["frio_bg_image_option"]);
PConfig::set(local_user(), 'frio', 'scheme', $_POST['frio_scheme']);
PConfig::set(local_user(), 'frio', 'nav_bg', $_POST['frio_nav_bg']);
PConfig::set(local_user(), 'frio', 'nav_icon_color', $_POST['frio_nav_icon_color']);
PConfig::set(local_user(), 'frio', 'link_color', $_POST['frio_link_color']);
PConfig::set(local_user(), 'frio', 'background_color', $_POST['frio_background_color']);
PConfig::set(local_user(), 'frio', 'contentbg_transp', $_POST['frio_contentbg_transp']);
PConfig::set(local_user(), 'frio', 'background_image', $_POST['frio_background_image']);
PConfig::set(local_user(), 'frio', 'bg_image_option', $_POST['frio_bg_image_option']);
PConfig::set(local_user(), 'frio', 'css_modified', time());
}
}
function theme_admin_post(App $a) {
function theme_admin_post(App $a)
{
if (!local_user()) {
return;
}
if (isset($_POST['frio-settings-submit'])) {
Config::set('frio', 'schema', $_POST["frio_schema"]);
Config::set('frio', 'nav_bg', $_POST["frio_nav_bg"]);
Config::set('frio', 'nav_icon_color', $_POST["frio_nav_icon_color"]);
Config::set('frio', 'link_color', $_POST["frio_link_color"]);
Config::set('frio', 'background_color', $_POST["frio_background_color"]);
Config::set('frio', 'contentbg_transp', $_POST["frio_contentbg_transp"]);
Config::set('frio', 'background_image', $_POST["frio_background_image"]);
Config::set('frio', 'bg_image_option', $_POST["frio_bg_image_option"]);
Config::set('frio', 'login_bg_image', $_POST["frio_login_bg_image"]);
Config::set('frio', 'login_bg_color', $_POST["frio_login_bg_color"]);
Config::set('frio', 'scheme', $_POST['frio_scheme']);
Config::set('frio', 'nav_bg', $_POST['frio_nav_bg']);
Config::set('frio', 'nav_icon_color', $_POST['frio_nav_icon_color']);
Config::set('frio', 'link_color', $_POST['frio_link_color']);
Config::set('frio', 'background_color', $_POST['frio_background_color']);
Config::set('frio', 'contentbg_transp', $_POST['frio_contentbg_transp']);
Config::set('frio', 'background_image', $_POST['frio_background_image']);
Config::set('frio', 'bg_image_option', $_POST['frio_bg_image_option']);
Config::set('frio', 'login_bg_image', $_POST['frio_login_bg_image']);
Config::set('frio', 'login_bg_color', $_POST['frio_login_bg_color']);
Config::set('frio', 'css_modified', time());
}
}
function theme_content(App $a) {
function theme_content(App $a)
{
if (!local_user()) {
return;
}
$arr = [];
$arr["schema"] = PConfig::get(local_user(), 'frio', 'schema');
$arr["nav_bg"] = PConfig::get(local_user(), 'frio', 'nav_bg');
$arr["nav_icon_color"] = PConfig::get(local_user(), 'frio', 'nav_icon_color');
$arr["link_color"] = PConfig::get(local_user(), 'frio', 'link_color');
$arr["bgcolor"] = PConfig::get(local_user(), 'frio', 'background_color');
$arr["contentbg_transp"] = PConfig::get(local_user(), 'frio', 'contentbg_transp');
$arr["background_image"] = PConfig::get(local_user(), 'frio', 'background_image');
$arr["bg_image_option"] = PConfig::get(local_user(), 'frio', 'bg_image_option');
$arr['scheme'] = PConfig::get(local_user(), 'frio', 'scheme', PConfig::get(local_user(), 'frio', 'schema'));
$arr['nav_bg'] = PConfig::get(local_user(), 'frio', 'nav_bg');
$arr['nav_icon_color'] = PConfig::get(local_user(), 'frio', 'nav_icon_color');
$arr['link_color'] = PConfig::get(local_user(), 'frio', 'link_color');
$arr['background_color'] = PConfig::get(local_user(), 'frio', 'background_color');
$arr['contentbg_transp'] = PConfig::get(local_user(), 'frio', 'contentbg_transp');
$arr['background_image'] = PConfig::get(local_user(), 'frio', 'background_image');
$arr['bg_image_option'] = PConfig::get(local_user(), 'frio', 'bg_image_option');
return frio_form($arr);
}
function theme_admin(App $a) {
function theme_admin(App $a)
{
if (!local_user()) {
return;
}
$arr = [];
$arr["schema"] = Config::get('frio', 'schema');
$arr["nav_bg"] = Config::get('frio', 'nav_bg');
$arr["nav_icon_color"] = Config::get('frio', 'nav_icon_color');
$arr["link_color"] = Config::get('frio', 'link_color');
$arr["bgcolor"] = Config::get('frio', 'background_color');
$arr["contentbg_transp"] = Config::get('frio', 'contentbg_transp');
$arr["background_image"] = Config::get('frio', 'background_image');
$arr["bg_image_option"] = Config::get('frio', 'bg_image_option');
$arr["login_bg_image"] = Config::get('frio', 'login_bg_image');
$arr["login_bg_color"] = Config::get('frio', 'login_bg_color');
$arr['scheme'] = Config::get('frio', 'scheme', Config::get('frio', 'scheme'));
$arr['nav_bg'] = Config::get('frio', 'nav_bg');
$arr['nav_icon_color'] = Config::get('frio', 'nav_icon_color');
$arr['link_color'] = Config::get('frio', 'link_color');
$arr['background_color'] = Config::get('frio', 'background_color');
$arr['contentbg_transp'] = Config::get('frio', 'contentbg_transp');
$arr['background_image'] = Config::get('frio', 'background_image');
$arr['bg_image_option'] = Config::get('frio', 'bg_image_option');
$arr['login_bg_image'] = Config::get('frio', 'login_bg_image');
$arr['login_bg_color'] = Config::get('frio', 'login_bg_color');
return frio_form($arr);
}
function frio_form($arr) {
require_once("view/theme/frio/php/schema.php");
function frio_form($arr)
{
require_once 'view/theme/frio/php/scheme.php';
$scheme_info = get_schema_info($arr["schema"]);
$disable = $scheme_info["overwrites"];
$scheme_info = get_scheme_info($arr['scheme']);
$disable = $scheme_info['overwrites'];
if (!is_array($disable)) {
$disable = [];
}
$scheme_choices = [];
$scheme_choices["---"] = L10n::t("Default");
$files = glob('view/theme/frio/schema/*.php');
$scheme_choices['---'] = L10n::t('Custom');
$files = glob('view/theme/frio/scheme/*.php');
if ($files) {
foreach ($files as $file) {
$f = basename($file, ".php");
$f = basename($file, '.php');
if ($f != 'default') {
$scheme_name = $f;
$scheme_name = ucfirst($f);
$scheme_choices[$f] = $scheme_name;
}
}
}
$background_image_help = "<strong>" . L10n::t("Note"). ": </strong>".L10n::t("Check image permissions if all users are allowed to visit the image");
$background_image_help = '<strong>' . L10n::t('Note') . ': </strong>' . L10n::t('Check image permissions if all users are allowed to see the image');
$t = get_markup_template('theme_settings.tpl');
$ctx = [
'$submit' => L10n::t('Submit'),
'$baseurl' => System::baseUrl(),
'$title' => L10n::t("Theme settings"),
'$schema' => ['frio_schema', L10n::t("Select scheme"), $arr["schema"], '', $scheme_choices],
'$nav_bg' => array_key_exists("nav_bg", $disable) ? "" : ['frio_nav_bg', L10n::t('Navigation bar background color'), $arr['nav_bg'], '', false],
'$nav_icon_color' => array_key_exists("nav_icon_color", $disable) ? "" : ['frio_nav_icon_color', L10n::t('Navigation bar icon color '), $arr['nav_icon_color'], '', false],
'$link_color' => array_key_exists("link_color", $disable) ? "" : ['frio_link_color', L10n::t('Link color'), $arr['link_color'], '', false],
'$bgcolor' => array_key_exists("bgcolor", $disable) ? "" : ['frio_background_color', L10n::t('Set the background color'), $arr['bgcolor'], '', false],
'$contentbg_transp' => array_key_exists("contentbg_transp", $disable) ? "" : ['frio_contentbg_transp', L10n::t("Content background opacity"), ((isset($arr["contentbg_transp"]) && $arr["contentbg_transp"] != "") ? $arr["contentbg_transp"] : 100), ''],
'$background_image' => array_key_exists("background_image", $disable) ? "" : ['frio_background_image', L10n::t('Set the background image'), $arr['background_image'], $background_image_help, false],
'$title' => L10n::t('Theme settings'),
'$scheme' => ['frio_scheme', L10n::t('Select color scheme'), $arr['scheme'], '', $scheme_choices],
'$nav_bg' => array_key_exists('nav_bg', $disable) ? '' : ['frio_nav_bg', L10n::t('Navigation bar background color'), $arr['nav_bg'], '', false],
'$nav_icon_color' => array_key_exists('nav_icon_color', $disable) ? '' : ['frio_nav_icon_color', L10n::t('Navigation bar icon color '), $arr['nav_icon_color'], '', false],
'$link_color' => array_key_exists('link_color', $disable) ? '' : ['frio_link_color', L10n::t('Link color'), $arr['link_color'], '', false],
'$background_color' => array_key_exists('background_color', $disable) ? '' : ['frio_background_color', L10n::t('Set the background color'), $arr['background_color'], '', false],
'$contentbg_transp' => array_key_exists('contentbg_transp', $disable) ? '' : ['frio_contentbg_transp', L10n::t('Content background opacity'), defaults($arr, 'contentbg_transp', 100), ''],
'$background_image' => array_key_exists('background_image', $disable) ? '' : ['frio_background_image', L10n::t('Set the background image'), $arr['background_image'], $background_image_help, false],
'$bg_image_options_title' => L10n::t('Background image style'),
'$bg_image_options' => Image::get_options($arr),
];
if (array_key_exists("login_bg_image", $arr) && !array_key_exists("login_bg_image", $disable)) {
$ctx['$login_bg_image'] = ['frio_login_bg_image', L10n::t('Login page background image'), $arr['login_bg_image'], $background_image_help, false];
}
if (array_key_exists("login_bg_color", $arr) && !array_key_exists("login_bg_color", $disable)) {
$ctx['$login_bg_color'] = ['frio_login_bg_color', L10n::t('Login page background color'), $arr['login_bg_color'], L10n::t('Leave background image and color empty for theme defaults'), false];
if (array_key_exists('login_bg_image', $arr) && !array_key_exists('login_bg_image', $disable)) {
$ctx['$login_bg_image'] = ['frio_login_bg_image', L10n::t('Login page background image'), $arr['login_bg_image'], $background_image_help, false];
}
if (array_key_exists('login_bg_color', $arr) && !array_key_exists('login_bg_color', $disable)) {
$ctx['$login_bg_color'] = ['frio_login_bg_color', L10n::t('Login page background color'), $arr['login_bg_color'], L10n::t('Leave background image and color empty for theme defaults'), false];
}
$o = replace_macros($t, $ctx);
+35 -9
View File
@@ -24,9 +24,10 @@ and open the template in the editor.
body {
padding-top: 110px;
background-color: $bgcolor;
background-color: $background_color;
background-image: url("$background_image");
background-size: $background_size_img;
background-repeat: $background_repeat;
background-attachment: fixed;
color: #777;
/*color: #555;*/
@@ -3154,12 +3155,30 @@ section .profile-match-wrapper {
* Login page
*/
#login-submit-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
float: right;
}
#lost-password-link { flex-grow: 2; }
#login-lost-password-link {
margin-bottom: 10px;
float: right;
}
#div_id_remember {
float: left;
}
#id_password_wrapper {
margin-bottom: unset;
}
#login_openid {
clear: both;
}
#register-link {
color: white;
background: #8ad0a1;
width: 100%;
}
#login-end {
clear: both;
}
.mod-home.is-not-singleuser,
.mod-login {
@@ -3184,12 +3203,15 @@ section .profile-match-wrapper {
margin-top: 2.5%;
}
.mod-home.is-not-singleuser .login-form > #login-extra-links {
margin-top: 4em;
}
.mod-home.is-not-singleuser .login-form > #login-form label,
.mod-login #content #login-form label {
color: #eee;
}
.mod-home.is-not-singleuser .login-panel-content,
.mod-login .login-panel-content {
background-color: rgba(255,255,255,.85);
@@ -3203,11 +3225,15 @@ section .profile-match-wrapper {
}
.mod-home.is-not-singleuser .login-form > #login-form,
.mod-home.is-not-singleuser .login-form > #login-extra-links,
.mod-login #content #login-form {
background-color: #fff;
padding: 1em;
position: relative;
margin-top: 4em;
}
.mod-home.is-not-singleuser .login-form > #login-extra-links {
margin-top: unset;
background-color: white;
}
.mod-home.is-not-singleuser .login-form > #login-form label,
@@ -3215,7 +3241,7 @@ section .profile-match-wrapper {
color: #444;
}
.mod-home.is-not-singleuser .login-form > #login-form::before,
.mod-home.is-not-singleuser .login-form::before,
.mod-login #content #login-form::before {
display: block;
position: absolute;
@@ -3228,7 +3254,7 @@ section .profile-match-wrapper {
z-index: -1;
}
.mod-home.is-not-singleuser .login-form > #login-form::after,
.mod-home.is-not-singleuser .login-form::after,
.mod-login #content #login-form::after {
display: block;
position: absolute;

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 239 KiB

Before

Width:  |  Height:  |  Size: 750 KiB

After

Width:  |  Height:  |  Size: 750 KiB

+4 -8
View File
@@ -21,14 +21,10 @@ class Image
public static function get_options($arr)
{
$bg_image_options = [
'repeat' => [
'frio_bg_image_option', L10n::t("Repeat the image"), "repeat", L10n::t("Will repeat your image to fill the background."), ($arr["bg_image_option"] == "repeat")],
'stretch' => [
'frio_bg_image_option', L10n::t("Stretch"), "stretch", L10n::t("Will stretch to width/height of the image."), ($arr["bg_image_option"] == "stretch")],
'cover' => [
'frio_bg_image_option', L10n::t("Resize fill and-clip"), "cover", L10n::t("Resize to fill and retain aspect ratio."), ($arr["bg_image_option"] == "cover")],
'contain' => [
'frio_bg_image_option', L10n::t("Resize best fit"), "contain", L10n::t("Resize to best fit and retain aspect ratio."), ($arr["bg_image_option"] == "contain")],
'stretch' => ['frio_bg_image_option', L10n::t('Top Banner'), 'stretch', L10n::t('Resize image to the width of the screen and show background color below on long pages.'), ($arr['bg_image_option'] == 'stretch')],
'cover' => ['frio_bg_image_option', L10n::t('Full screen'), 'cover', L10n::t('Resize image to fill entire screen, clipping either the right or the bottom.'), ($arr['bg_image_option'] == 'cover')],
'contain' => ['frio_bg_image_option', L10n::t('Single row mosaic'), 'contain', L10n::t('Resize image to repeat it on a single row, either vertical or horizontal.'), ($arr['bg_image_option'] == 'contain')],
'repeat' => ['frio_bg_image_option', L10n::t('Mosaic'), 'repeat', L10n::t('Repeat image to fill the screen.'), ($arr['bg_image_option'] == 'repeat')],
];
return $bg_image_options;
+4 -4
View File
@@ -43,10 +43,10 @@ if (!isset($minimal)) {
if (is_null($uid)) {
$uid = Profile::getThemeUid();
}
$schema = PConfig::get($uid, 'frio', 'schema');
if (($schema) && ($schema != '---')) {
if (file_exists('view/theme/frio/schema/' . $schema . '.php')) {
$schemefile = 'view/theme/frio/schema/' . $schema . '.php';
$scheme = PConfig::get($uid, 'frio', 'scheme', PConfig::get($uid, 'frio', 'schema'));
if (($scheme) && ($scheme != '---')) {
if (file_exists('view/theme/frio/scheme/' . $scheme . '.php')) {
$schemefile = 'view/theme/frio/scheme/' . $scheme . '.php';
require_once $schemefile;
}
} else {
+13 -14
View File
@@ -14,24 +14,23 @@ use Friendica\App;
*
* @todo Check if this is really needed.
*/
function load_page(App $a) {
if(isset($_GET["mode"]) && ($_GET["mode"] == "minimal")) {
require "view/theme/frio/minimal.php";
} elseif((isset($_GET["mode"]) && ($_GET["mode"] == "none"))) {
require "view/theme/frio/none.php";
function load_page(App $a)
{
if (isset($_GET['mode']) && ($_GET['mode'] == 'minimal')) {
require 'view/theme/frio/minimal.php';
} elseif ((isset($_GET['mode']) && ($_GET['mode'] == 'none'))) {
require 'view/theme/frio/none.php';
} else {
$template = 'view/theme/' . current_theme() . '/'
. ((x($a->page,'template')) ? $a->page['template'] : 'default' ) . '.php';
if(file_exists($template))
require_once($template);
else
require_once(str_replace('theme/' . current_theme() . '/', '', $template));
$template = 'view/theme/' . $a->getCurrentTheme() . '/'
. ((x($a->page, 'template')) ? $a->page['template'] : 'default' ) . '.php';
if (file_exists($template)) {
require_once $template;
} else {
require_once str_replace('theme/' . $a->getCurrentTheme() . '/', '', $template);
}
}
}
/**
* @brief Check if page is a modal page
*
-74
View File
@@ -1,74 +0,0 @@
<?php
/**
* @brief: Get info header of the shema
*
* This function parses the header of the shemename.php file for inormations like
* Author, Description and Overwrites. Most of the code comes from the Addon::getInfo()
* function. We use this to get the variables which get overwritten through the shema.
* All color variables which get overwritten through the theme have to be
* listed (comma seperated) in the shema header under Overwrites:
* This seemst not to be the best solution. We need to investigate further.
*
* @param string $schema Name of the shema
* @return array With theme information
* 'author' => Author Name
* 'description' => Schema description
* 'version' => Schema version
* 'overwrites' => Variables which overwriting custom settings
*/
use Friendica\Core\PConfig;
function get_schema_info($schema){
$theme = current_theme();
$themepath = "view/theme/" . $theme . "/";
$schema = PConfig::get(local_user(),'frio', 'schema');
$info=[
'name' => $schema,
'description' => "",
'author' => [],
'version' => "",
'overwrites' => []
];
if (!is_file($themepath . "schema/" . $schema . ".php")) return $info;
$f = file_get_contents($themepath . "schema/" . $schema . ".php");
$r = preg_match("|/\*.*\*/|msU", $f, $m);
if ($r){
$ll = explode("\n", $m[0]);
foreach( $ll as $l ) {
$l = trim($l,"\t\n\r */");
if ($l!=""){
list($k,$v) = array_map("trim", explode(":",$l,2));
$k= strtolower($k);
if ($k=="author"){
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['author'][] = ['name'=>$m[1], 'link'=>$m[2]];
} else {
$info['author'][] = ['name'=>$v];
}
} elseif ($k == "overwrites") {
$theme_settings = explode(',',str_replace(' ','', $v));
foreach ($theme_settings as $key => $value) {
$info["overwrites"][$value] = true;
}
} else {
if (array_key_exists($k,$info)){
$info[$k]=$v;
}
}
}
}
}
return $info;
}
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* @brief: Get info header of the scheme
*
* This function parses the header of the schemename.php file for informations like
* Author, Description and Overwrites. Most of the code comes from the Addon::getInfo()
* function. We use this to get the variables which get overwritten through the scheme.
* All color variables which get overwritten through the theme have to be
* listed (comma separated) in the scheme header under Overwrites:
* This seems not to be the best solution. We need to investigate further.
*
* @param string $scheme Name of the scheme
* @return array With theme information
* 'author' => Author Name
* 'description' => Scheme description
* 'version' => Scheme version
* 'overwrites' => Variables which overwriting custom settings
*/
use Friendica\Core\PConfig;
require_once 'boot.php';
function get_scheme_info($scheme)
{
$theme = get_app()->getCurrentTheme();
$themepath = 'view/theme/' . $theme . '/';
$scheme = PConfig::get(local_user(), 'frio', 'scheme', PConfig::get(local_user(), 'frio', 'scheme'));
$info = [
'name' => $scheme,
'description' => '',
'author' => [],
'version' => '',
'overwrites' => []
];
if (!is_file($themepath . 'scheme/' . $scheme . '.php')) return $info;
$f = file_get_contents($themepath . 'scheme/' . $scheme . '.php');
$r = preg_match('|/\*.*\*/|msU', $f, $m);
if ($r) {
$ll = explode("\n", $m[0]);
foreach ($ll as $l) {
$l = trim($l, "\t\n\r */");
if ($l != '') {
list($k, $v) = array_map('trim', explode(':', $l, 2));
$k = strtolower($k);
if ($k == 'author') {
$r = preg_match('|([^<]+)<([^>]+)>|', $v, $m);
if ($r) {
$info['author'][] = ['name' => $m[1], 'link' => $m[2]];
} else {
$info['author'][] = ['name' => $v];
}
} elseif ($k == 'overwrites') {
$theme_settings = explode(',', str_replace(' ', '', $v));
foreach ($theme_settings as $key => $value) {
$info['overwrites'][$value] = true;
}
} else {
if (array_key_exists($k, $info)) {
$info[$k] = $v;
}
}
}
}
}
return $info;
}
+1 -1
View File
@@ -16,7 +16,7 @@
<?php $frio = "view/theme/frio"; ?>
<?php if(x($page,'htmlhead')) echo $page['htmlhead']; ?>
</head>
<body id=\"top\">";
<body id="top">
<?php if($_SERVER['REQUEST_URI'] == "/"){header('Location: /login');} ?>
<a href="#content" class="sr-only sr-only-focusable">Skip to main content</a>
<?php
+16
View File
@@ -0,0 +1,16 @@
<?php
/*
* Name: Blue
* Author: Rabuzarus
*
* List here all variables which will get overwritten through this scheme
* Overwrites: nav_bg, nav_icon_color, link_color, background_color, login_bg_color, contentbg_transp
*/
$nav_bg = "#708fa0";
$nav_icon_color = "#fff";
$link_color = "#6fdbe8";
$background_color = "#ededed";
$login_bg_color = "#ededed";
$contentbg_transp = 100;
@@ -1,13 +1,13 @@
<?php
/* Licence: AGP
* Author: rabuzarus
* Overwrites: nav_bg, nav_icon_color, link_color, bgcolor, contentbg_transp, background_image, bg_image_option, link_hover_color
* Overwrites: nav_bg, nav_icon_color, link_color, background_color, contentbg_transp, background_image, bg_image_option, link_hover_color
*/
$nav_bg = "#000";
$nav_icon_color = "#e355e0";
$link_color = "#e355e0";
$bgcolor = "#fff";
$background_color = "#fff";
$contentbg_transp = 100;
$background_image = "img/bg_circle.png";
$bg_image_option = "repeat";
@@ -3,13 +3,13 @@
* Name: Red
* Author: Rabuzarus
*
* List here all variables which will get overwritten through this schema
* Overwrites: nav_bg, nav_icon_color, link_color, bgcolor, contentbg_transp
* List here all variables which will get overwritten through this scheme
* Overwrites: nav_bg, nav_icon_color, link_color, background_color, contentbg_transp
*/
$nav_bg = "#870000";
$nav_icon_color = "#f5f5f5";
$link_color = "#b50404";
$bgcolor = "#ededed";
$background_color = "#ededed";
$contentbg_transp = 95;
+68 -62
View File
@@ -8,7 +8,7 @@ use Friendica\Model\Profile;
require_once 'view/theme/frio/php/PHPColors/Color.php';
$schemecss = "";
$schemecss = '';
$schemecssfile = false;
$scheme_modified = 0;
@@ -19,15 +19,15 @@ if ($a->module !== 'install') {
PConfig::load($uid, 'frio');
// Load the profile owners pconfig.
$schema = PConfig::get($uid, "frio", "schema");
$nav_bg = PConfig::get($uid, "frio", "nav_bg");
$nav_icon_color = PConfig::get($uid, "frio", "nav_icon_color");
$link_color = PConfig::get($uid, "frio", "link_color");
$bgcolor = PConfig::get($uid, "frio", "background_color");
$contentbg_transp = PConfig::get($uid, "frio", "contentbg_transp");
$background_image = PConfig::get($uid, "frio", "background_image");
$bg_image_option = PConfig::get($uid, "frio", "bg_image_option");
$modified = PConfig::get($uid, "frio", "css_modified");
$scheme = PConfig::get($uid, 'frio', 'scheme', PConfig::get($uid, 'frio', 'schema'));
$nav_bg = PConfig::get($uid, 'frio', 'nav_bg');
$nav_icon_color = PConfig::get($uid, 'frio', 'nav_icon_color');
$link_color = PConfig::get($uid, 'frio', 'link_color');
$background_color = PConfig::get($uid, 'frio', 'background_color');
$contentbg_transp = PConfig::get($uid, 'frio', 'contentbg_transp');
$background_image = PConfig::get($uid, 'frio', 'background_image');
$bg_image_option = PConfig::get($uid, 'frio', 'bg_image_option');
$modified = PConfig::get($uid, 'frio', 'css_modified');
// There is maybe the case that the user did never modify the theme settings.
// In this case we store the present time.
@@ -38,17 +38,17 @@ if ($a->module !== 'install') {
Config::load('frio');
// Load frios system config.
$schema = Config::get("frio", "schema");
$nav_bg = Config::get("frio", "nav_bg");
$nav_icon_color = Config::get("frio", "nav_icon_color");
$link_color = Config::get("frio", "link_color");
$bgcolor = Config::get("frio", "background_color");
$contentbg_transp = Config::get("frio", "contentbg_transp");
$background_image = Config::get("frio", "background_image");
$bg_image_option = Config::get("frio", "bg_image_option");
$login_bg_image = Config::get("frio", "login_bg_image");
$login_bg_color = Config::get("frio", "login_bg_color");
$modified = Config::get("frio", "css_modified");
$scheme = Config::get('frio', 'scheme', Config::get('frio', 'schema'));
$nav_bg = Config::get('frio', 'nav_bg');
$nav_icon_color = Config::get('frio', 'nav_icon_color');
$link_color = Config::get('frio', 'link_color');
$background_color = Config::get('frio', 'background_color');
$contentbg_transp = Config::get('frio', 'contentbg_transp');
$background_image = Config::get('frio', 'background_image');
$bg_image_option = Config::get('frio', 'bg_image_option');
$login_bg_image = Config::get('frio', 'login_bg_image');
$login_bg_color = Config::get('frio', 'login_bg_color');
$modified = Config::get('frio', 'css_modified');
// There is maybe the case that the user did never modify the theme settings.
// In this case we store the present time.
@@ -59,60 +59,59 @@ if ($a->module !== 'install') {
}
// Now load the scheme. If a value is changed above, we'll keep the settings
// If not, we'll keep those defined by the schema
// Setting $schema to '' wasn't working for some reason, so we'll check it's
// If not, we'll keep those defined by the scheme
// Setting $scheme to '' wasn't working for some reason, so we'll check it's
// not --- like the mobile theme does instead.
// Allow layouts to over-ride the schema.
if (x($_REQUEST, 'schema')) {
$schema = $_REQUEST['schema'];
// Allow layouts to over-ride the scheme.
if (x($_REQUEST, 'scheme')) {
$scheme = $_REQUEST['scheme'];
}
// Sanitize the data.
$schema = !empty($schema) ? basename($schema) : "";
$scheme = !empty($scheme) ? basename($scheme) : '';
if (($schema) && ($schema != '---')) {
if (file_exists('view/theme/frio/schema/' . $schema . '.php')) {
$schemefile = 'view/theme/frio/schema/' . $schema . '.php';
if (($scheme) && ($scheme != '---')) {
if (file_exists('view/theme/frio/scheme/' . $scheme . '.php')) {
$schemefile = 'view/theme/frio/scheme/' . $scheme . '.php';
require_once $schemefile;
}
if (file_exists('view/theme/frio/schema/' . $schema . '.css')) {
$schemecssfile = 'view/theme/frio/schema/' . $schema . '.css';
if (file_exists('view/theme/frio/scheme/' . $scheme . '.css')) {
$schemecssfile = 'view/theme/frio/scheme/' . $scheme . '.css';
}
}
// If we haven't got a schema, load the default. We shouldn't touch this - we
// If we haven't got a scheme, load the default. We shouldn't touch this - we
// should leave it for admins to define for themselves.
// default.php and default.css MUST be symlinks to existing schema files.
if (! $schema) {
if (file_exists('view/theme/frio/schema/default.php')) {
$schemefile = 'view/theme/frio/schema/default.php';
// default.php and default.css MUST be symlinks to existing scheme files.
if (!$scheme) {
if (file_exists('view/theme/frio/scheme/default.php')) {
$schemefile = 'view/theme/frio/scheme/default.php';
require_once $schemefile;
}
if (file_exists('view/theme/frio/schema/default.css')) {
$schemecssfile = 'view/theme/frio/schema/default.css';
if (file_exists('view/theme/frio/scheme/default.css')) {
$schemecssfile = 'view/theme/frio/scheme/default.css';
}
}
//Set some defaults - we have to do this after pulling owner settings, and we have to check for each setting
//individually. If we don't, we'll have problems if a user has set one, but not all options.
$nav_bg = (empty($nav_bg) ? "#708fa0" : $nav_bg);
$nav_icon_color = (empty($nav_icon_color) ? "#fff" : $nav_icon_color);
$link_color = (empty($link_color) ? "#6fdbe8" : $link_color);
$bgcolor = (empty($bgcolor) ? "#ededed" : $bgcolor);
$nav_bg = (empty($nav_bg) ? '#708fa0' : $nav_bg);
$nav_icon_color = (empty($nav_icon_color) ? '#fff' : $nav_icon_color);
$link_color = (empty($link_color) ? '#6fdbe8' : $link_color);
$background_color = (empty($background_color) ? '#ededed' : $background_color);
// The background image can not be empty. So we use a dummy jpg if no image was set.
$background_image = (empty($background_image) ? 'img/none.jpg' : $background_image);
$modified = (empty($modified) ? time() :$modified);
$modified = (empty($modified) ? time() : $modified);
// set a default login bg image if no custom image and no custom bg color are set.
if (empty($login_bg_image) && empty($login_bg_color)) {
$login_bg_image = (empty($login_bg_image) ? 'img/login_bg.jpg' : $login_bg_image);
$login_bg_image = 'img/login_bg.jpg';
}
$login_bg_color = (empty($login_bg_color) ? "#ededed" : $login_bg_color);
$login_bg_color = (empty($login_bg_color) ? '#ededed' : $login_bg_color);
$contentbg_transp = ((isset($contentbg_transp) && $contentbg_transp != "") ? $contentbg_transp : 100);
$contentbg_transp = ((isset($contentbg_transp) && $contentbg_transp != '') ? $contentbg_transp : 100);
// Calculate some colors in dependance of existing colors.
// Some colors are calculated to don't have too many selection
@@ -153,29 +152,35 @@ if (!isset($link_hover_color)) {
if (!isset($bg_image_option)) {
$bg_image_option = null;
}
switch ($bg_image_option) {
case "stretch":
$background_size_img = "100%";
case 'stretch':
$background_size_img = '100%';
$background_repeat = 'no-repeat';
break;
case "cover":
$background_size_img ="cover";
case 'cover':
$background_size_img = 'cover';
$background_repeat = 'no-repeat';
break;
case "repeat":
$background_size_img = "auto";
case 'repeat':
$background_size_img = 'auto';
$background_repeat = 'repeat';
break;
case "contain":
$background_size_img = "contain";
case 'contain':
$background_size_img = 'contain';
$background_repeat = 'repeat';
break;
default:
$background_size_img = "auto";
$background_size_img = 'auto';
$background_repeat = 'no-repeat';
break;
}
// Convert transparency level from percentage to opacity value.
$contentbg_transp = $contentbg_transp / 100;
$options = [
$options = [
'$nav_bg' => $nav_bg,
'$nav_icon_color' => $nav_icon_color,
'$nav_icon_hover_color' => $nav_icon_hover_color,
@@ -184,10 +189,11 @@ $options = [
'$menu_background_hover_color' => $menu_background_hover_color,
'$btn_primary_color' => $nav_icon_color,
'$btn_primary_hover_color' => $menu_background_hover_color,
'$bgcolor' => $bgcolor,
'$background_color' => $background_color,
'$contentbg_transp' => $contentbg_transp,
'$background_image' => $background_image,
'$background_size_img' => $background_size_img,
'$background_repeat' => $background_repeat,
'$login_bg_image' => $login_bg_image,
'$login_bg_color' => $login_bg_color
];
@@ -214,13 +220,13 @@ $etag = md5($css);
// Set a header for caching.
header('Cache-Control: public');
header('ETag: "'.$etag.'"');
header('Last-Modified: '.$modified);
header('ETag: "' . $etag . '"');
header('Last-Modified: ' . $modified);
// Only send the CSS file if it was changed.
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$cached_modified = gmdate('r', strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']));
$cached_etag = str_replace(['"', "-gzip"], ['', ''],
$cached_etag = str_replace(['"', '-gzip'], ['', ''],
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']));
if (($cached_modified == $modified) && ($cached_etag == $etag)) {
+3 -1
View File
@@ -4,6 +4,8 @@
<input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" value="1" {{if $field.2}}checked="checked"{{/if}} aria-checked="{{if $field.2}}true{{else}}false{{/if}}" aria-describedby="{{$field.0}}_tip" {{if $field.4}}{{$field.4}}{{/if}}>
<label for="id_{{$field.0}}">
{{$field.1}}
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</label>
</div>
</div>
@@ -6,6 +6,8 @@
{{if $field.4}}<span class="required">{{$field.4}}</span>{{/if}}
<span class="input-group-addon"><i></i></span>
</div>
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div id="end_{{$field.0}}" class="field_end"></div>
</div>
+3 -1
View File
@@ -2,5 +2,7 @@
<div class="form-group field custom">
<label for="{{$field.0}}">{{$field.1}}</label>
{{$field.2}}
<span class="help-block" id="{{$field.0}}_tip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</div>
@@ -6,6 +6,8 @@
{{if $field.4}}<span class="required">{{$field.4}}</span>{{/if}}
<span class="input-group-addon image-select"><i class="fa fa-picture-o"></i></span>
</div>
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div id="end_{{$field.0}}" class="field_end"></div>
</div>
+3 -1
View File
@@ -2,6 +2,8 @@
<div id="id_{{$field.0}}_wrapper" class="form-group field input">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}}<span class="required"> {{$field.4}}</span>{{/if}}</label>
<input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}"{{if $field.6 eq "email"}} type="email"{{elseif $field.6 eq "url"}} type="url"{{else}} type="text"{{/if}} value="{{$field.2|escape:'html'}}"{{if $field.4 eq "required"}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}} aria-describedby="{{$field.0}}_tip">
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div class="clear"></div>
</div>
@@ -2,6 +2,8 @@
<div class="form-group field checkbox">
<input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" value="{{$field.3|escape:'html'}}" {{if $field.2}}checked="checked"{{/if}} aria-checked="{{if $field.2}}true{{else}}false{{/if}}" aria-describedby="{{$field.0}}_tip">
<label for="id_{{$field.0}}">{{$field.1}}</label>
<span class="help-block" role="tooltip" id="{{$field.0}}_tip">{{$field.4}}</span>
{{if $field.4}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.4}}</span>
{{/if}}
</div>
<div class="clear"></div>
+3 -1
View File
@@ -2,6 +2,8 @@
<div id="id_{{$field.0}}_wrapper" class="form-group field input openid">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}</label>
<input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2|escape:'html'}}" aria-describedby="{{$field.0}}_tip">
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div class="clear"></div>
</div>
+3 -1
View File
@@ -2,6 +2,8 @@
<div id="id_{{$field.0}}_wrapper" class="form-group field input password">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}}<span class="required"> {{$field.4}}</span>{{/if}}</label>
<input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="password" value="{{$field.2|escape:'html'}}" {{if $field.4 eq "required"}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}} aria-describedby="{{$field.0}}_tip">
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div class="clear"></div>
</div>
+3 -1
View File
@@ -4,7 +4,9 @@
<input type="radio" name="{{$field.0}}" id="id_{{$field.0}}_{{$field.2}}" value="{{$field.2}}" {{if $field.4}}checked{{/if}} aria-checked="{{if $field.4}}true{{else}}false{{/if}}" aria-describedby="{{$field.0}}_{{$field.2}}_tip">
<label for="id_{{$field.0}}_{{$field.2}}">
{{$field.1}}
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_{{$field.2}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</label>
</div>
</div>
</div>
+4 -2
View File
@@ -4,5 +4,7 @@
<select name="{{$field.0}}" id="id_{{$field.0}}" class="form-control" aria-describedby="{{$field.0}}_tip">
{{foreach $field.4 as $opt=>$val}}<option value="{{$opt|escape:'html'}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
</select>
<span class="help-block" id="{{$field.0}}_tip">{{$field.3}}</span>
</div>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</div>
@@ -4,5 +4,7 @@
<select class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" aria-describedby="{{$field.0}}_tip">
{{$field.4}}
</select>
<span class="help-block" id="{{$field.0}}_tip">{{$field.3}}</span>
</div>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</div>
+3 -1
View File
@@ -2,6 +2,8 @@
<div class="form-group field textarea">
<label for="id_{{$field.0}}">{{$field.1}}</label>
<textarea class="form-control text-autosize" name="{{$field.0}}" id="id_{{$field.0}}" {{if $field.4}}{{$field.4}}{{/if}} aria-describedby="{{$field.0}}_tip">{{$field.2}}</textarea>
<span id="{{$field.0}}_tip" class="help-block" role="tooltip">{{$field.3}}</span>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
<div class="clear"></div>
</div>
@@ -5,6 +5,8 @@
<select class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" {{if $field.5=="preview"}}onchange="previewTheme(this);"{{/if}} aria-describedby="{{$field.0}}_tip" >
{{foreach $field.4 as $opt=>$val}}<option value="{{$opt}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
</select>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
{{if $field.5=="preview"}}<div id="theme-preview"></div>{{/if}}
</div>
</div>
@@ -14,6 +14,8 @@
<span class="toggle-handle btn btn-default btn-xs"></span>
</div>
</div>
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3}}</span>
{{/if}}
</div>
<div class="clear"></div>
+12 -3
View File
@@ -8,6 +8,10 @@
<div id="login_standard">
{{include file="field_input.tpl" field=$lname}}
{{include file="field_password.tpl" field=$lpassword}}
<div id="login-lost-password-link">
<a href="lostpass" title="{{$lostpass|escape:'html'}}" id="lost-password-link" >{{$lostlink}}</a>
</div>
<div id="login-end"></div>
</div>
{{if $openid}}
@@ -19,10 +23,7 @@
{{include file="field_checkbox.tpl" field=$lremember}}
<div id="login-submit-wrapper">
<a href="lostpass" title="{{$lostpass|escape:'html'}}" id="lost-password-link">{{$lostlink}}</a>
<div class="pull-right" >
{{if $register}}<a href="register" title="{{$register.title|escape:'html'}}" id="register-link" class="btn btn-default">{{$register.desc}}</a>{{/if}}
<button type="submit" name="submit" id="login-submit-button" class="btn btn-primary" value="{{$login|escape:'html'}}">{{$login|escape:'html'}}</button>
</div>
</div>
@@ -32,7 +33,15 @@
<input type="hidden" name="{{$k}}" value="{{$v|escape:'html'}}" />
{{/foreach}}
<div id="login-end"></div>
</div>
</form>
{{if $register}}
<div id="login-extra-links">
<h3 id="login-head" class="sr-only">{{$register.title|escape:'html'}}</h3>
<a href="register" title="{{$register.title|escape:'html'}}" id="register-link" class="btn btn-default">{{$register.desc}}</a>
</div>
{{/if}}
<script type="text/javascript"> $(document).ready(function() { $("#id_{{$lname.0}}").focus();} );</script>
+3 -2
View File
@@ -4,13 +4,13 @@
<script src="{{$baseurl}}/view/theme/frio/frameworks/jRange/jquery.range.js"></script>
<script type="text/javascript" src="{{$baseurl}}/view/js/ajaxupload.js" ></script>
{{include file="field_select.tpl" field=$schema}}
{{include file="field_select.tpl" field=$scheme}}
{{if $nav_bg}}{{include file="field_colorinput.tpl" field=$nav_bg}}{{/if}}
{{if $nav_icon_color}}{{include file="field_colorinput.tpl" field=$nav_icon_color}}{{/if}}
{{if $link_color}}{{include file="field_colorinput.tpl" field=$link_color}}{{/if}}
{{if $bgcolor}}{{include file="field_colorinput.tpl" field=$bgcolor}}{{/if}}
{{if $background_color}}{{include file="field_colorinput.tpl" field=$background_color}}{{/if}}
{{* The slider for the content opacity - We use no template for this since it is only used at this page *}}
{{if $contentbg_transp}}
@@ -25,6 +25,7 @@
{{if $background_image}}{{include file="field_fileinput.tpl" field=$background_image}}{{/if}}
<div id="frio_bg_image_options" style="display: none;">
<label>{{$bg_image_options_title}}:</label>
{{foreach $bg_image_options as $options}}
{{include file="field_radio.tpl" field=$options}}
{{/foreach}}
+47 -47
View File
@@ -18,7 +18,7 @@ use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Profile;
$frio = "view/theme/frio";
$frio = 'view/theme/frio';
global $frio;
@@ -34,21 +34,21 @@ function frio_init(App $a)
$style = PConfig::get(local_user(), 'frio', 'style');
$frio = "view/theme/frio";
$frio = 'view/theme/frio';
global $frio;
// if the device is a mobile device set js is_mobile
// variable so the js scripts can use this information
if ($a->is_mobile || $a->is_tablet) {
$a->page["htmlhead"] .= <<< EOT
$a->page['htmlhead'] .= <<< EOT
<script type="text/javascript">
var is_mobile = 1;
</script>
EOT;
}
if ($style == "") {
if ($style == '') {
$style = Config::get('frio', 'style');
}
}
@@ -62,7 +62,7 @@ function frio_install()
Addon::registerHook('acl_lookup_end', 'view/theme/frio/theme.php', 'frio_acl_lookup');
Addon::registerHook('display_item', 'view/theme/frio/theme.php', 'frio_display_item');
logger("installed theme frio");
logger('installed theme frio');
}
function frio_uninstall()
@@ -74,7 +74,7 @@ function frio_uninstall()
Addon::unregisterHook('acl_lookup_end', 'view/theme/frio/theme.php', 'frio_acl_lookup');
Addon::unregisterHook('display_item', 'view/theme/frio/theme.php', 'frio_display_item');
logger("uninstalled theme frio");
logger('uninstalled theme frio');
}
/**
@@ -92,26 +92,26 @@ function frio_uninstall()
function frio_item_photo_links(App $a, &$body_info)
{
$occurence = 0;
$p = Plaintext::getBoundariesPosition($body_info['html'], "<a", ">");
$p = Plaintext::getBoundariesPosition($body_info['html'], '<a', '>');
while ($p !== false && ($occurence++ < 500)) {
$link = substr($body_info['html'], $p['start'], $p['end'] - $p['start']);
$matches = [];
preg_match("/\/photos\/[\w]+\/image\/([\w]+)/", $link, $matches);
preg_match('/\/photos\/[\w]+\/image\/([\w]+)/', $link, $matches);
if ($matches) {
// Replace the link for the photo's page with a direct link to the photo itself
$newlink = str_replace($matches[0], "/photo/{$matches[1]}", $link);
// Add a "quiet" parameter to any redir links to prevent the "XX welcomes YY" info boxes
$newlink = preg_replace("/href=\"([^\"]+)\/redir\/([^\"]+)&url=([^\"]+)\"/", 'href="$1/redir/$2&quiet=1&url=$3"', $newlink);
$newlink = preg_replace('/href="([^"]+)\/redir\/([^"]+)&url=([^"]+)"/', 'href="$1/redir/$2&quiet=1&url=$3"', $newlink);
// Having any arguments to the link for Colorbox causes it to fetch base64 code instead of the image
$newlink = preg_replace("/\/[?&]zrl=([^&\"]+)/", '', $newlink);
$newlink = preg_replace('/\/[?&]zrl=([^&"]+)/', '', $newlink);
$body_info['html'] = str_replace($link, $newlink, $body_info['html']);
}
$p = Plaintext::getBoundariesPosition($body_info['html'], "<a", ">", $occurence);
$p = Plaintext::getBoundariesPosition($body_info['html'], '<a', '>', $occurence);
}
}
@@ -127,10 +127,10 @@ function frio_item_photo_links(App $a, &$body_info)
*/
function frio_item_photo_menu(App $a, &$arr)
{
foreach ($arr["menu"] as $k => $v) {
foreach ($arr['menu'] as $k => $v) {
if (strpos($v, 'poke/?f=&c=') === 0 || strpos($v, 'message/new/') === 0) {
$v = "javascript:addToModal('" . $v . "'); return false;";
$arr["menu"][$k] = $v;
$v = 'javascript:addToModal(\'' . $v . '\'); return false;';
$arr['menu'][$k] = $v;
}
}
}
@@ -149,9 +149,9 @@ function frio_item_photo_menu(App $a, &$arr)
*/
function frio_contact_photo_menu(App $a, &$args)
{
$cid = $args["contact"]["id"];
$pokelink = $args["menu"]["poke"][1];
$pmlink = $args["menu"]["pm"][1];
$cid = $args['contact']['id'];
$pokelink = $args['menu']['poke'][1];
$pmlink = $args['menu']['pm'][1];
// Set the the indicator for opening the status, profile and photo pages
// in a new tab to false if the contact a dfrn (friendica) contact
@@ -160,12 +160,12 @@ function frio_contact_photo_menu(App $a, &$args)
// friendica servers as remote user or visitor
//
// The value for opening in a new tab is e.g. when
// $args["menu"]["status"][2] is true. If the value of the [2] key is true
// $args['menu']['status'][2] is true. If the value of the [2] key is true
// and if it's a friendica contact we set it to false
foreach ($args["menu"] as $k => $v) {
if ($k === "status" || $k === "profile" || $k === "photos") {
$v[2] = (($args["contact"]["network"] === "dfrn") ? false : true);
$args["menu"][$k][2] = $v[2];
foreach ($args['menu'] as $k => $v) {
if ($k === 'status' || $k === 'profile' || $k === 'photos') {
$v[2] = (($args['contact']['network'] === 'dfrn') ? false : true);
$args['menu'][$k][2] = $v[2];
}
}
@@ -173,11 +173,11 @@ function frio_contact_photo_menu(App $a, &$args)
// Later we can make conditions in the corresponing templates (e.g.
// contact_template.tpl)
if (strpos($pokelink, 'poke/?f=&c=' . $cid) !== false) {
$args["menu"]["poke"][3] = "modal";
$args['menu']['poke'][3] = 'modal';
}
if (strpos($pmlink, 'message/new/' . $cid) !== false) {
$args["menu"]["pm"][3] = "modal";
$args['menu']['pm'][3] = 'modal';
}
}
@@ -231,43 +231,43 @@ function frio_remote_nav($a, &$nav)
// user info
$r = q("SELECT `micro` FROM `contact` WHERE `uid` = %d AND `self`", intval($a->user['uid']));
$r[0]['photo'] = (DBM::is_result($r) ? $a->remove_baseurl($r[0]['micro']) : "images/person-48.jpg");
$r[0]['photo'] = (DBM::is_result($r) ? $a->remove_baseurl($r[0]['micro']) : 'images/person-48.jpg');
$r[0]['name'] = $a->user['username'];
} elseif (!local_user() && remote_user()) {
$r = q("SELECT `name`, `nick`, `micro` AS `photo` FROM `contact` WHERE `id` = %d", intval(remote_user()));
$nav['remote'] = L10n::t("Guest");
$nav['remote'] = L10n::t('Guest');
} elseif (Profile::getMyURL()) {
$r = q("SELECT `name`, `nick`, `photo` FROM `gcontact`
WHERE `addr` = '%s' AND `network` = 'dfrn'",
dbesc($webbie));
$nav['remote'] = L10n::t("Visitor");
$nav['remote'] = L10n::t('Visitor');
} else {
$r = false;
}
if (DBM::is_result($r)) {
$nav['userinfo'] = [
'icon' => (DBM::is_result($r) ? $r[0]['photo'] : "images/person-48.jpg"),
'icon' => (DBM::is_result($r) ? $r[0]['photo'] : 'images/person-48.jpg'),
'name' => $r[0]['name'],
];
}
if (!local_user() && !empty($server_url)) {
$nav['logout'] = [$server_url . '/logout', L10n::t('Logout'), "", L10n::t('End this session')];
$nav['logout'] = [$server_url . '/logout', L10n::t('Logout'), '', L10n::t('End this session')];
// user menu
$nav['usermenu'][] = [$server_url . '/profile/' . $a->user['nickname'], L10n::t('Status'), "", L10n::t('Your posts and conversations')];
$nav['usermenu'][] = [$server_url . '/profile/' . $a->user['nickname'] . '?tab=profile', L10n::t('Profile'), "", L10n::t('Your profile page')];
$nav['usermenu'][] = [$server_url . '/photos/' . $a->user['nickname'], L10n::t('Photos'), "", L10n::t('Your photos')];
$nav['usermenu'][] = [$server_url . '/videos/' . $a->user['nickname'], L10n::t('Videos'), "", L10n::t('Your videos')];
$nav['usermenu'][] = [$server_url . '/events/', L10n::t('Events'), "", L10n::t('Your events')];
$nav['usermenu'][] = [$server_url . '/profile/' . $a->user['nickname'], L10n::t('Status'), '', L10n::t('Your posts and conversations')];
$nav['usermenu'][] = [$server_url . '/profile/' . $a->user['nickname'] . '?tab=profile', L10n::t('Profile'), '', L10n::t('Your profile page')];
$nav['usermenu'][] = [$server_url . '/photos/' . $a->user['nickname'], L10n::t('Photos'), '', L10n::t('Your photos')];
$nav['usermenu'][] = [$server_url . '/videos/' . $a->user['nickname'], L10n::t('Videos'), '', L10n::t('Your videos')];
$nav['usermenu'][] = [$server_url . '/events/', L10n::t('Events'), '', L10n::t('Your events')];
// navbar links
$nav['network'] = [$server_url . '/network', L10n::t('Network'), "", L10n::t('Conversations from your friends')];
$nav['events'] = [$server_url . '/events', L10n::t('Events'), "", L10n::t('Events and Calendar')];
$nav['messages'] = [$server_url . '/message', L10n::t('Messages'), "", L10n::t('Private mail')];
$nav['settings'] = [$server_url . '/settings', L10n::t('Settings'), "", L10n::t('Account settings')];
$nav['contacts'] = [$server_url . '/contacts', L10n::t('Contacts'), "", L10n::t('Manage/edit friends and contacts')];
$nav['network'] = [$server_url . '/network', L10n::t('Network'), '', L10n::t('Conversations from your friends')];
$nav['events'] = [$server_url . '/events', L10n::t('Events'), '', L10n::t('Events and Calendar')];
$nav['messages'] = [$server_url . '/message', L10n::t('Messages'), '', L10n::t('Private mail')];
$nav['settings'] = [$server_url . '/settings', L10n::t('Settings'), '', L10n::t('Account settings')];
$nav['contacts'] = [$server_url . '/contacts', L10n::t('Contacts'), '', L10n::t('Manage/edit friends and contacts')];
$nav['sitename'] = $a->config['sitename'];
}
}
@@ -289,18 +289,18 @@ function frio_acl_lookup(App $a, &$results)
{
require_once 'mod/contacts.php';
$nets = x($_GET, "nets") ? notags(trim($_GET["nets"])) : "";
$nets = x($_GET, 'nets') ? notags(trim($_GET['nets'])) : '';
// we introduce a new search type, r should do the same query like it's
// done in /mod/contacts for connections
if ($results["type"] !== "r") {
if ($results['type'] !== 'r') {
return;
}
$sql_extra = '';
if ($results["search"]) {
$search_txt = dbesc(protect_sprintf(preg_quote($results["search"])));
$sql_extra .= " AND (`attag` LIKE '%%" . dbesc($search_txt) . "%%' OR `name` LIKE '%%" . dbesc($search_txt) . "%%' OR `nick` LIKE '%%" . dbesc($search_txt) . "%%' OR `addr` LIKE '%%" . dbesc($search_txt) . "%%') ";
if ($results['search']) {
$search_txt = dbesc(protect_sprintf(preg_quote($results['search'])));
$sql_extra .= " AND (`attag` LIKE '%%" . dbesc($search_txt) . "%%' OR `name` LIKE '%%" . dbesc($search_txt) . "%%' OR `nick` LIKE '%%" . dbesc($search_txt) . "%%') ";
}
if ($nets) {
@@ -311,7 +311,7 @@ function frio_acl_lookup(App $a, &$results)
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `pending` $sql_extra ", intval($_SESSION['uid']));
if (DBM::is_result($r)) {
$total = $r[0]["total"];
$total = $r[0]['total'];
}
$sql_extra3 = Widget::unavailableNetworks();
@@ -328,8 +328,8 @@ function frio_acl_lookup(App $a, &$results)
}
}
$results["items"] = $contacts;
$results["tot"] = $total;
$results['items'] = $contacts;
$results['tot'] = $total;
}
/**
+7
View File
@@ -91,6 +91,13 @@ nav ul {
width: 100% !important; height: 110px !important;
}
#login-extra-links, #login-form {
/* width: 341px; */
width: 100%;
}
#id_remember_label {
width: unset;
}
}
@media screen and (max-width: 480px) {
+50
View File
@@ -2422,10 +2422,60 @@ aside #div_id_remember label {
float: inherit;
}
#login-group {
overflow: hidden;
}
#login-head {
position: unset;
width: unset;
height: unset;
margin-bottom: 10px;
}
div #wrapper_username {
padding: 0px;
}
div #wrapper_password {
padding: 0px;
margin-bottom: 0px;
}
#div_id_remember {
float: left;
width: unset;
}
#remember_tip {
display: none;
}
#login-submit-wrapper {
float: right;
}
#login-form {
margin-top: 20px;
}
#login-extra-links, #login-form {
/* width: 341px; */
width: 341px;
clear: both;
border-top: 3px solid white;
padding-top: 20px;
}
aside div #login-submit-button {
margin-left:0px;
}
#login-lost-password-link {
margin-bottom: 10px;
float: right;
}
aside #register-link, aside #lost-password-link {
display: block;
}