diff --git a/cache/lastCache.txt b/cache/lastCache.txt index dd5a19d..1185c30 100644 --- a/cache/lastCache.txt +++ b/cache/lastCache.txt @@ -1 +1 @@ -1546551286 \ No newline at end of file +1548436334 \ No newline at end of file diff --git a/content/00-Welcome/01-Write-Content.md b/content/00-Welcome/02-Write-Content.md similarity index 100% rename from content/00-Welcome/01-Write-Content.md rename to content/00-Welcome/02-Write-Content.md diff --git a/content/00-Welcome/02-Get-Help.md b/content/00-Welcome/03-Get-Help.md similarity index 100% rename from content/00-Welcome/02-Get-Help.md rename to content/00-Welcome/03-Get-Help.md diff --git a/content/00-Welcome/04-markdown-test.md b/content/00-Welcome/04-markdown-test.md new file mode 100644 index 0000000..3174e5f --- /dev/null +++ b/content/00-Welcome/04-markdown-test.md @@ -0,0 +1,290 @@ +# Markdown Reference and Test Page + +Markdown is a simple and universal syntax for text formatting. More and more writers switch to markdown, because they can format their text during the writing process without using any format-buttons. Once they are familiar with the markdown syntax, they can write formatted text much easier and faster than with any standard HTML-editor. + +Developers love markdown, because it is much cleaner and saver than HTML. And they can easily convert markdown to a lot of other document formats like HTML and others. + +If you develop a theme for TYPEMILL, please take care that all elements on this page are designed properly. + +##Table of Contents + +To create a table of contents, simply write `[TOC]` in a separate line. It will be replaced with a table of contents like this automatically. + +[TOC] + +## Headlines + +``` +Headlines are simply done with hash chars like this: +# First Level Headline +## Second Level Headline +### Third Level Headline +#### Fourth Level Headline +##### Fifth Level Headline +###### Sixth Level Headline +``` + +### Third Level Headline {.myclass} + +A third headline is more decent and lower prioritized than a second level headline. + +#### Fourth Level Headline + +A fourth level headline is more decent and lower prioritized than a third level headline. + +##### Fifth Level Headline + +A fifth level headline is more decent and lower prioritized than a fourth level headline. + +##### Sixth Level Headline + +A sixth level headline is more decent and lower prioritized than a fifths level headline. + +##Paragraph + +```` +A paragraph is a simple text-block separated with a new line above and below. +```` + +A paragraph is a simple text-block separated with a new line above and below. + +## Soft Linebreak + +```` +For a soft linebreak (eg. for dialoges in literature), add two spaces at the end of a line and use a simple return. +She said: "Hello" +He said: "again" +```` + +For a soft linebreak (eg. for dialoges in literature), add two spaces at the end of a line and use a simple return. + +She said: "Hello" +He said: "again" + +##Emphasis + +```` +For italic text use one *asterix* or one _underscore_. +For bold text use two **asterix** or two __underscores__. +```` + +For italic text use one *asterix* or one _underscore_. + +For bold text use two **asterix** or two __underscores__. + +##Lists + +```` +For an unordered list use a dash +- like +- this +Or use one asterix +* like +* this +For an ordered list use whatever number you want and add a dot: +1. like +1. this +```` + +For an unordered list use a dash + +- like +- this + +Or use one asterix + +* like +* this + +For an ordered list use whatever number you want and add a dot: + +1. like +2. this + +## Horizontal Rule + +``` +Easily created for example with three dashes like this: +--- +``` + +Easily created for example with three dashes like this: + +--- + +##Links + +```` +This is an ordinary [Link](http://typemill.net). +Links can also be [relative](/info). +You can also add a [title](http://typemill.net "typemill"). +You can even add [ids or classes](http://typemill.net){#myid .myclass}. +Or you can use a shortcut like http://typemill.net. +```` + +This is an ordinary [Link](http://typemill.net). + +Links can also be [relative](/info). + +You can also add a [title](http://typemill.net "typemill"). + +You can even add [ids or classes](http://typemill.net){#myid .myclass}. + +Or you can use a shortcut like http://typemill.net. + +##Images + +```` +The same rules as with links, but with a ! +![alt-text](media/markdown.png) +![alt-text](media/markdown.png "my title") +![alt-text](media/markdown.png "my title"){#myid .myclass width=100px} +```` + +The same rules as with links, but with a ! + +![alt-text](media/markdown.png){.imgClass} + +![alt-text](media/markdown.png "my title"){.imgClass} + +![alt-text](media/markdown.png "my title"){#myid .myclass width=100px} + +## Linked Images + +```` +You can link an image with a nested syntax like this: +[![alt-text](media/markdown.png)](https://typemill.net) +```` + +You can link an image with a nested syntax like this: + +[![alt-text](media/markdown.png){.imgClass}](https://typemill.net) + +## Image Position + +```` +You can controll the image position with the classes .left, .right and .middle like this: +![alt-text](media/markdown.png){.left} +![alt-text](media/markdown.png){.right} +![alt-text](media/markdown.png){.middle} +```` + +![image float left](media/markdown.png){.left} + +The first image should float on the left side of this paragraph. This might not work with all themes. If you are a theme developer, please ensure that you support the image classes "left", "right" and "middle". + +![image float right](media/markdown.png){.right} + +The second image should float on the right side of this paragraph. This might not work with all themes. If you are a theme developer, please ensure that you support the image classes "left", "right" and "middle". + +![image middle](media/markdown.png){.middle} + +The thirds image should be placed above this paragraph and centered to the middle of the content area. This might not work with all themes. If you are a theme developer, please ensure that you support the image classes "left", "right" and "middle". + +## Blockquote + +``` +There are always some women and men with wise words +> But I usually don't read them, to be honest. +``` + +There always some women and men with wise words + +> But I usually don't read them, to be honest. + +##Footnotes + +```` +You can write footnotes[^1] with markdown. +Scroll down to the end of the page[^2] and look for the footnotes. +Add the footnote text at the bottom of the page like this: +[^1]: Thank you for scrolling. +[^2]: This is the end of the page. +```` + +You can write footnotes[^1] with markdown. + +Scroll down to the end of the page[^2] and look for the footnotes. + +## Abbreviations + +```` +*[HTML]: Hyper Text Markup Language +*[W3C]: World Wide Web Consortium +```` + +You won't see the abbreviation directly, but if you write HTML or W3C somewhere, then you can see the tooltip with the explanation. + +*[HTML]: Hyper Text Markup Language + +*[W3C]: World Wide Web Consortium + +## Definition List + +```` +Apple +: Pomaceous fruit of plants of the genus Malus in the family Rosaceae. +Orange +: The fruit of an evergreen tree of the genus Citrus. +```` + +Apple +: Pomaceous fruit of plants of the genus Malus in +the family Rosaceae. + +Orange +: The fruit of an evergreen tree of the genus Citrus. + +## Tables + +```` +|name |usage | +|-----------|-----------| +| My Name | For Me | +| Your Name | For You | +```` + +| Name | Usage | +| --------- | ------- | +| My Name | For Me | +| Your Name | For You | + +## Code + +```` +Let us create some `` like this +```` + +Let us create some `` and now let us check, if a codeblock works: + +```` +Use four apostroph like this: +\`​``` + +\```` +```` + +## Math + +Please activate the math-plugin to use mathematical expressions with LaTeX syntax. You can choose between MathJax or the newer KaTeX library. MathJax is included from a CDN, KaTeX is included in the plugin. So if you don't want to fetch code from a CDN, use KaTeX instead. The markdown syntax in TYPEMILL is the same for both libraries. + +```` +Use inline LaTeX ``x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)`` with two backtipps like this. +```` + +Use inline LaTeX ``x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a)`` like this. + +```` +Or specify latex sytnax for a code-block like this: +​````latex +x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a) +​```` +```` + +​````latex +x = \int_{0^1}^1(-b \pm \sqrt{b^2-4ac})/(2a) +​```` + diff --git a/media/markdown.png b/media/markdown.png new file mode 100644 index 0000000..9470f08 Binary files /dev/null and b/media/markdown.png differ diff --git a/media/readme.txt b/media/readme.txt deleted file mode 100644 index 79e2539..0000000 --- a/media/readme.txt +++ /dev/null @@ -1 +0,0 @@ -just a placeholder for git \ No newline at end of file diff --git a/system/Controllers/FormController.php b/system/Controllers/FormController.php index 0a48368..58f570d 100644 --- a/system/Controllers/FormController.php +++ b/system/Controllers/FormController.php @@ -19,7 +19,7 @@ class FormController extends Controller reset($params); $pluginName = key($params); $referer = $request->getHeader('HTTP_REFERER'); - + # simple bot check with honeypot if(isset($params[$pluginName]['personal-mail'])) { @@ -31,6 +31,35 @@ class FormController extends Controller unset($params[$pluginName]['personal-mail']); } + #recaptcha check + if(isset($params['g-recaptcha-response'])) + { + $recaptchaApi = 'https://www.google.com/recaptcha/api/siteverify'; + $settings = $this->c->get('settings'); + $secret = isset($settings['plugins'][$pluginName]['recaptcha_secretkey']) ? $settings['plugins'][$pluginName]['recaptcha_secretkey'] : false; + $recaptchaRequest = ['secret' => $secret, 'response' => $params['g-recaptcha-response']]; + + # use key 'http' even if you send the request to https://... + $options = array( + 'http' => array( + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => http_build_query($recaptchaRequest), + 'timeout' => 5 + ) + ); + + $context = stream_context_create($options); + $result = file_get_contents($recaptchaApi, false, $context); + $result = json_decode($result); + + if ($result === FALSE || $result->success === FALSE) + { + $this->c->flash->addMessage('publicform', 'bot'); + return $response->withRedirect($referer[0]); + } + } + if(isset($params[$pluginName])) { # validate the user-input diff --git a/system/Controllers/SettingsController.php b/system/Controllers/SettingsController.php index bf3ae27..63594a9 100644 --- a/system/Controllers/SettingsController.php +++ b/system/Controllers/SettingsController.php @@ -30,6 +30,17 @@ class SettingsController extends Controller { if($request->isPost()) { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR $referer[0] !== $base_url . '/tm/settings' ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('settings.show')); + } + $settings = \Typemill\Settings::getUserSettings(); $params = $request->getParams(); $newSettings = isset($params['settings']) ? $params['settings'] : false; @@ -47,16 +58,16 @@ class SettingsController extends Controller 'editor' => $newSettings['editor'], ); - $copyright = $this->getCopyright(); + $copyright = $this->getCopyright(); $validate->settings($newSettings, $copyright, 'settings'); } else { $this->c->flash->addMessage('error', 'Wrong Input'); - return $response->withRedirect($this->c->router->pathFor('settings.show')); + return $response->withRedirect($this->c->router->pathFor('settings.show')); } - + if(isset($_SESSION['errors'])) { $this->c->flash->addMessage('error', 'Please correct the errors'); @@ -133,7 +144,7 @@ class SettingsController extends Controller /* iterate through the plugins in the stored user settings */ foreach($userSettings['plugins'] as $pluginName => $pluginUserSettings) - { + { /* add plugin to plugin Data, if active, set it first */ /* if plugin is active, list it first */ if($userSettings['plugins'][$pluginName]['active'] == true) @@ -170,11 +181,19 @@ class SettingsController extends Controller /* if the plugin defines forms and fields, so that the user can edit the plugin settings in the frontend */ if(isset($pluginOriginalSettings['forms']['fields'])) { + # if the plugin defines frontend fields + if(isset($pluginOriginalSettings['public'])) + { + $pluginOriginalSettings['forms']['fields']['recaptcha'] = ['type' => 'checkbox', 'label' => 'Google Recaptcha', 'checkboxlabel' => 'Activate Recaptcha' ]; + $pluginOriginalSettings['forms']['fields']['recaptcha_webkey'] = ['type' => 'text', 'label' => 'Recaptcha Website Key', 'help' => 'Add the recaptcha website key here. You can get the key from the recaptcha website.', 'description' => 'The website key is mandatory if you activate the recaptcha field']; + $pluginOriginalSettings['forms']['fields']['recaptcha_secretkey'] = ['type' => 'text', 'label' => 'Recaptcha Secret Key', 'help' => 'Add the recaptcha secret key here. You can get the key from the recaptcha website.', 'description' => 'The secret key is mandatory if you activate the recaptcha field']; + } + /* get all the fields and prefill them with the dafault-data, the user-data or old input data */ $fields = $fieldsModel->getFields($userSettings, 'plugins', $pluginName, $pluginOriginalSettings); /* overwrite original plugin form definitions with enhanced form objects */ - $plugins[$pluginName]['forms']['fields'] = $fields; + $plugins[$pluginName]['forms']['fields'] = $fields; } } @@ -192,7 +211,18 @@ class SettingsController extends Controller public function saveThemes($request, $response, $args) { if($request->isPost()) - { + { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR $referer[0] !== $base_url . '/tm/themes' ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('themes.show')); + } + $userSettings = \Typemill\Settings::getUserSettings(); $params = $request->getParams(); $themeName = isset($params['theme']) ? $params['theme'] : false; @@ -231,11 +261,22 @@ class SettingsController extends Controller return $response->withRedirect($this->c->router->pathFor('themes.show')); } } - + public function savePlugins($request, $response, $args) { if($request->isPost()) { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR $referer[0] !== $base_url . '/tm/plugins' ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('plugins.show')); + } + $userSettings = \Typemill\Settings::getUserSettings(); $pluginSettings = array(); $userInput = $request->getParams(); @@ -307,6 +348,14 @@ class SettingsController extends Controller $originalFields[$fieldName] = $fieldValue; } } + + # if the plugin defines frontend fields + if(isset($originalSettings['public'])) + { + $originalFields['recaptcha'] = ['type' => 'checkbox', 'label' => 'Google Recaptcha', 'checkboxlabel' => 'Activate Recaptcha' ]; + $originalFields['recaptcha_webkey'] = ['type' => 'text', 'label' => 'Recaptcha Website Key', 'help' => 'Add the recaptcha website key here. You can get the key from the recaptcha website.', 'description' => 'The website key is mandatory if you activate the recaptcha field']; + $originalFields['recaptcha_secretkey'] = ['type' => 'text', 'label' => 'Recaptcha Secret Key', 'help' => 'Add the recaptcha secret key here. You can get the key from the recaptcha website.', 'description' => 'The secret key is mandatory if you activate the recaptcha field']; + } /* take the user input data and iterate over all fields and values */ foreach($userInput as $fieldName => $fieldValue) @@ -386,6 +435,17 @@ class SettingsController extends Controller { if($request->isPost()) { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR $referer[0] !== $base_url . '/tm/user/new' ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('user.new')); + } + $params = $request->getParams(); $user = new User(); $userroles = $user->getUserroles(); @@ -409,7 +469,18 @@ class SettingsController extends Controller public function updateUser($request, $response, $args) { if($request->isPost()) - { + { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR strpos($referer[0], $base_url . '/tm/user/') === false ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('user.list')); + } + $params = $request->getParams(); $user = new User(); $userroles = $user->getUserroles(); @@ -456,6 +527,17 @@ class SettingsController extends Controller { if($request->isPost()) { + $referer = $request->getHeader('HTTP_REFERER'); + $uri = $request->getUri(); + $base_url = $uri->getBaseUrl(); + + # security, users should not be able to fake post with settings from other typemill pages. + if(!isset($referer[0]) OR strpos($referer[0], $base_url . '/tm/user/') === false ) + { + $this->c->flash->addMessage('error', 'illegal referer'); + return $response->withRedirect($this->c->router->pathFor('user.list')); + } + $params = $request->getParams(); $validate = new Validation(); $user = new User(); diff --git a/system/Extensions/ParsedownExtension.php b/system/Extensions/ParsedownExtension.php index 85ce938..23c80ad 100644 --- a/system/Extensions/ParsedownExtension.php +++ b/system/Extensions/ParsedownExtension.php @@ -18,15 +18,19 @@ class ParsedownExtension extends \ParsedownExtra array_unshift($this->BlockTypes['['], 'TableOfContents'); } - function text($text) + public function text($text) { $Elements = $this->textElements($text); return $Elements; } - function markup($Elements, $relurl) - { + public function markup($Elements, $relurl) + { + + # make relurl available for other functions + $this->relurl = $relurl; + # convert to markup $markup = $this->elements($Elements); @@ -39,7 +43,7 @@ class ParsedownExtension extends \ParsedownExtra # create table of contents if(isset($this->DefinitionData['TableOfContents'])) { - $TOC = $this->buildTOC($this->headlines, $relurl); + $TOC = $this->buildTOC($this->headlines); $markup = preg_replace('%(]*>\[TOC\]

)%i', $TOC, $markup); } @@ -105,10 +109,10 @@ class ParsedownExtension extends \ParsedownExtra return $Block; } } - + # build the markup for table of contents - protected function buildTOC($headlines, $relurl) + protected function buildTOC($headlines) { $markup = '