diff --git a/.htaccess b/.htaccess index c22aef8..03dfe07 100644 --- a/.htaccess +++ b/.htaccess @@ -14,7 +14,8 @@ RewriteEngine On # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # Use this to redirect www to non-wwww on apache servers -# RewriteRule ^(.*)$ http://%1/$1 [R=301,L] +RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] +RewriteRule ^(.*)$ http://%1/$1 [R=301,L] # Use this to redirect slash/ to url without slash on apache servers # RewriteCond %{REQUEST_FILENAME} !-d diff --git a/system/Controllers/ContentController.php b/system/Controllers/ContentController.php index 1e2e3b2..fee84ce 100644 --- a/system/Controllers/ContentController.php +++ b/system/Controllers/ContentController.php @@ -75,18 +75,20 @@ abstract class ContentController } $response = $response->withoutHeader('Server'); - $response = $response->withoutHeader('X-Powered-By'); + $response = $response->withAddedHeader('X-Powered-By', 'Typemill'); - if($this->c->request->getUri()->getScheme() == 'https') + if(!isset($this->settings['headersoff']) or !$this->settings['headersoff']) { - $response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000'); + $response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); + $response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN'); + $response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block'); + $response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade'); + if($this->c->request->getUri()->getScheme() == 'https') + { + $response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000'); + } } - $response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); - $response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN'); - $response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block'); - $response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade'); - return $this->c->view->render($response, $route, $data); } diff --git a/system/Controllers/Controller.php b/system/Controllers/Controller.php index 7dc2064..320f650 100644 --- a/system/Controllers/Controller.php +++ b/system/Controllers/Controller.php @@ -13,9 +13,13 @@ abstract class Controller { protected $c; + protected $settings; + public function __construct(ContainerInterface $c) { - $this->c = $c; + $this->c = $c; + $this->settings = $this->c->get('settings'); + $this->c->dispatcher->dispatch('onTwigLoaded'); } @@ -31,17 +35,19 @@ abstract class Controller } $response = $response->withoutHeader('Server'); - if($this->c->request->getUri()->getScheme() == 'https') - { - $response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000'); - } - - $response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); - $response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN'); - $response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block'); - $response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade'); $response = $response->withAddedHeader('X-Powered-By', 'Typemill'); + if(!isset($this->settings['headersoff']) or !$this->settings['headersoff']) + { + $response = $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); + $response = $response->withAddedHeader('X-Frame-Options', 'SAMEORIGIN'); + $response = $response->withAddedHeader('X-XSS-Protection', '1;mode=block'); + $response = $response->withAddedHeader('Referrer-Policy', 'no-referrer-when-downgrade'); + if($this->c->request->getUri()->getScheme() == 'https') + { + $response = $response->withAddedHeader('Strict-Transport-Security', 'max-age=63072000'); + } + } return $this->c->view->render($response, $route, $data); } diff --git a/system/Controllers/PageController.php b/system/Controllers/PageController.php index 1e07d24..60f3afa 100644 --- a/system/Controllers/PageController.php +++ b/system/Controllers/PageController.php @@ -31,8 +31,7 @@ class PageController extends Controller $item = false; $home = false; $breadcrumb = false; - $settings = $this->c->get('settings'); - $pathToContent = $settings['rootPath'] . $settings['contentFolder']; + $pathToContent = $this->settings['rootPath'] . $this->settings['contentFolder']; $cache = new WriteCache(); $uri = $request->getUri()->withUserInfo(''); $base_url = $uri->getBaseUrl(); @@ -77,7 +76,7 @@ class PageController extends Controller # get meta-Information $writeMeta = new WriteMeta(); - $theme = $settings['theme']; + $theme = $this->settings['theme']; # check if there is a custom theme css $customcss = $writeMeta->checkFile('cache', $theme . '-custom.css'); @@ -87,13 +86,13 @@ class PageController extends Controller } $logo = false; - if(isset($settings['logo']) && $settings['logo'] != '') + if(isset($this->settings['logo']) && $this->settings['logo'] != '') { - $logo = 'media/files/' . $settings['logo']; + $logo = 'media/files/' . $this->settings['logo']; } $favicon = false; - if(isset($settings['favicon']) && $settings['favicon'] != '') + if(isset($this->settings['favicon']) && $this->settings['favicon'] != '') { $favicon = true; } @@ -128,7 +127,7 @@ class PageController extends Controller { return $this->render404($response, array( 'navigation' => $navigation, - 'settings' => $settings, + 'settings' => $this->settings, 'base_url' => $base_url, 'title' => false, 'content' => false, @@ -191,7 +190,7 @@ class PageController extends Controller $this->c->dispatcher->dispatch('onOriginalLoaded', new OnOriginalLoaded($contentMD)); # makes sure that you always have the full meta with title, description and all the rest. - $metatabs = $writeMeta->completePageMeta($contentMD, $settings, $item); + $metatabs = $writeMeta->completePageMeta($contentMD, $this->settings, $item); # dispatch meta $metatabs = $this->c->dispatcher->dispatch('onMetaLoaded', new OnMetaLoaded($metatabs))->getData(); @@ -202,7 +201,7 @@ class PageController extends Controller $itemUrl = isset($item->urlRel) ? $item->urlRel : false; /* initialize parsedown */ - $parsedown = new ParsedownExtension($base_url, $settings['headlineanchors']); + $parsedown = new ParsedownExtension($base_url, $this->settings); /* set safe mode to escape javascript and html in markdown */ $parsedown->setSafeMode(true); @@ -217,7 +216,7 @@ class PageController extends Controller /* extract the h1 headline*/ $contentParts = explode("", $contentHTML, 2); - $title = isset($contentParts[0]) ? strip_tags($contentParts[0]) : $settings['title']; + $title = isset($contentParts[0]) ? strip_tags($contentParts[0]) : $this->settings['title']; $contentHTML = isset($contentParts[1]) ? $contentParts[1] : $contentHTML; @@ -245,7 +244,7 @@ class PageController extends Controller elseif($logo) { $img_url = $logo; - $pathinfo = pathinfo($settings['logo']); + $pathinfo = pathinfo($this->settings['logo']); $img_alt = $pathinfo['filename']; } } @@ -256,7 +255,7 @@ class PageController extends Controller $firstImage = array('img_url' => $base_url . '/' . $img_url, 'img_alt' => $img_alt); } - $route = empty($args) && isset($settings['themes'][$theme]['cover']) ? '/cover.twig' : '/index.twig'; + $route = empty($args) && isset($this->settings['themes'][$theme]['cover']) ? '/cover.twig' : '/index.twig'; return $this->render($response, $route, [ 'home' => $home, @@ -265,7 +264,7 @@ class PageController extends Controller 'content' => $contentHTML, 'item' => $item, 'breadcrumb' => $breadcrumb, - 'settings' => $settings, + 'settings' => $this->settings, 'metatabs' => $metatabs, 'base_url' => $base_url, 'image' => $firstImage, diff --git a/system/Controllers/SettingsController.php b/system/Controllers/SettingsController.php index 9ac4dd8..2d20028 100644 --- a/system/Controllers/SettingsController.php +++ b/system/Controllers/SettingsController.php @@ -102,7 +102,9 @@ class SettingsController extends Controller 'displayErrorDetails' => isset($newSettings['displayErrorDetails']) ? true : null, 'twigcache' => isset($newSettings['twigcache']) ? true : null, 'proxy' => isset($newSettings['proxy']) ? true : null, - 'trustedproxies' => $newSettings['trustedproxies'] + 'trustedproxies' => $newSettings['trustedproxies'], + 'headersoff' => isset($newSettings['headersoff']) ? true : null, + 'urlschemes' => $newSettings['urlschemes'], ); # https://www.slimframework.com/docs/v3/cookbook/uploading-files.html; @@ -120,7 +122,6 @@ class SettingsController extends Controller { $newSettings['images']['live']['height'] = $imgheight; } - } else { diff --git a/system/Extensions/ParsedownExtension.php b/system/Extensions/ParsedownExtension.php index d78ccd3..c383eea 100644 --- a/system/Extensions/ParsedownExtension.php +++ b/system/Extensions/ParsedownExtension.php @@ -6,12 +6,22 @@ use \URLify; class ParsedownExtension extends \ParsedownExtra { - function __construct($baseUrl = '', $showAnchor = NULL) + function __construct($baseUrl = '', $settings = NULL) { parent::__construct(); # show anchor next to headline? - $this->showAnchor = $showAnchor; + $this->showAnchor = isset($settings['headlineanchors']) ? $settings['headlineanchors'] : false; + + # extend link schemes + $urlschemes = ( isset($settings['urlschemes']) && !empty($settings['urlschemes']) ) ? explode(",", $settings['urlschemes']) : false; + if($urlschemes) + { + foreach($urlschemes as $urlschema) + { + $this->safeLinksWhitelist[] = $urlschema; + } + } # base url is needed for media/images and relative links (e.g. if www.mydomain.com/mywebsite) $this->baseUrl = $baseUrl; @@ -33,7 +43,17 @@ class ParsedownExtension extends \ParsedownExtra # identify Table Of contents after footnotes and links array_unshift($this->BlockTypes['['], 'TableOfContents'); } - + + public function extendLinksWhitelist($linktypes) + { + /* + if($linktypes) + { + $this->safeLinksWhitelist[] = ; + } + */ + } + public function setVisualMode() { $this->visualMode = true; diff --git a/system/Settings.php b/system/Settings.php index 295b6c0..c3da0ea 100644 --- a/system/Settings.php +++ b/system/Settings.php @@ -177,6 +177,8 @@ class Settings 'twigcache' => true, 'proxy' => true, 'trustedproxies' => true, + 'headersoff' => true, + 'urlschemes' => true, ]; # cleanup the existing usersettings diff --git a/system/author/editor/editor-blox.twig b/system/author/editor/editor-blox.twig index 2649f6c..00702f6 100644 --- a/system/author/editor/editor-blox.twig +++ b/system/author/editor/editor-blox.twig @@ -86,7 +86,7 @@ {% if item.elementType == "folder" %} -
+
diff --git a/system/author/js/vue-meta.js b/system/author/js/vue-meta.js index 6bfc346..42faa5e 100644 --- a/system/author/js/vue-meta.js +++ b/system/author/js/vue-meta.js @@ -60,10 +60,12 @@ let meta = new Vue({ if(this.currentTab == 'Content') { editor.showBlox = 'show'; + posts.showPosts = 'show'; } else { editor.showBlox = 'hidden'; + posts.showPosts = 'hidden'; } return 'tab-' + this.currentTab.toLowerCase() } diff --git a/system/author/js/vue-posts.js b/system/author/js/vue-posts.js index afc8fc8..1745101 100644 --- a/system/author/js/vue-posts.js +++ b/system/author/js/vue-posts.js @@ -25,7 +25,8 @@ let posts = new Vue({ folderid: false, format: /[@#*()=\[\]{};:"\\|,.<>\/]/, root: document.getElementById("main").dataset.url, - editormode: document.getElementById("data-navi").dataset.editormode + editormode: document.getElementById("data-navi").dataset.editormode, + showPosts: 'show', } }, methods: { diff --git a/system/author/settings/system.twig b/system/author/settings/system.twig index 48a5659..bd99b07 100644 --- a/system/author/settings/system.twig +++ b/system/author/settings/system.twig @@ -201,6 +201,20 @@ {{ errors.settings.trustedproxies | first }} {% endif %}
+
+ + +
+
+ + + {% if errors.settings.urlschemes %} + {{ errors.settings.urlschemes | first }} + {% endif %} +