--- /dev/null
+*.idea
+*.iml
--- /dev/null
+0.5 Lykos -
+ + Initial beta release
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
--- /dev/null
+scientia - cognizance, insight, knowledge
+scientia utilis - useful knowledge
--- /dev/null
+0.5 - Lykos
--- /dev/null
+:root{--background-body:#fff;--background:#efefef;--background-alt:#f7f7f7;--selection:#9e9e9e;--text-main:#363636;--text-bright:#000;--text-muted:#70777f;--links:#0076d1;--focus:rgba(0,150,191,0.67);--border:#dbdbdb;--code:#000;--animation-duration:0.1s;--button-hover:#ddd;--scrollbar-thumb:#d5d5d5;--scrollbar-thumb-hover:#c4c4c4;--form-placeholder:#949494;--form-text:#000;--variable:#39a33c;--highlight:#ff0;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E")}html{scrollbar-color:#d5d5d5 #fff;scrollbar-color:var(--scrollbar-thumb) var(--background-body);scrollbar-width:thin}body{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Segoe UI Emoji,Apple Color Emoji,Noto Color Emoji,sans-serif;line-height:1.4;max-width:800px;margin:20px auto;padding:0 10px;word-wrap:break-word;color:#363636;color:var(--text-main);background:#fff;background:var(--background-body);text-rendering:optimizeLegibility}button,input,textarea{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}h1{font-size:2.2em;margin-top:0}h1,h2,h3,h4,h5,h6{margin-bottom:12px;margin-top:24px}h1,h2,h3,h4,h5,h6,strong{color:#000;color:var(--text-bright)}b,h1,h2,h3,h4,h5,h6,strong,th{font-weight:600}q:after,q:before{content:none}blockquote,q{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus);margin:1.5em 0;padding:.5em 1em;font-style:italic}blockquote>footer{font-style:normal;border:0}address,blockquote cite{font-style:normal}a[href^=mailto\:]:before{content:"📧 "}a[href^=tel\:]:before{content:"📞 "}a[href^=sms\:]:before{content:"💬 "}mark{background-color:#ff0;background-color:var(--highlight);border-radius:2px;padding:0 2px;color:#000}button,input[type=button],input[type=checkbox],input[type=radio],input[type=range],input[type=submit],select{cursor:pointer}input:not([type=checkbox]):not([type=radio]),select{display:block}button,input,select,textarea{color:#000;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}input[type=checkbox],input[type=radio]{height:1em;width:1em}input[type=radio]{border-radius:100%}input{vertical-align:top}label{vertical-align:middle;margin-bottom:4px;display:inline-block}button,input:not([type=checkbox]):not([type=radio]),input[type=range],select,textarea{-webkit-appearance:none}textarea{display:block;margin-right:0;box-sizing:border-box;resize:vertical}textarea:not([cols]){width:100%}textarea:not([rows]){min-height:40px;height:140px}select{background:#efefef url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E") calc(100% - 12px) 50%/12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat;padding-right:35px}select::-ms-expand{display:none}select[multiple]{padding-right:10px;background-image:none;overflow-y:auto}button,input[type=button],input[type=submit]{padding-right:30px;padding-left:30px}button:hover,input[type=button]:hover,input[type=submit]:hover{background:#ddd;background:var(--button-hover)}button:focus,input:focus,select:focus,textarea:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}button:active,input[type=button]:active,input[type=checkbox]:active,input[type=radio]:active,input[type=range]:active,input[type=submit]:active{transform:translateY(2px)}button:disabled,input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;opacity:.5}::-moz-placeholder{color:#949494;color:var(--form-placeholder)}:-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::placeholder{color:#949494;color:var(--form-placeholder)}fieldset{border:1px solid rgba(0,150,191,.67);border:1px solid var(--focus);border-radius:6px;margin:0 0 12px;padding:10px}legend{font-size:.9em;font-weight:600}input[type=range]{margin:10px 0;padding:10px 0;background:transparent}input[type=range]:focus{outline:none}input[type=range]::-webkit-slider-runnable-track{width:100%;height:9.5px;-webkit-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}input[type=range]::-webkit-slider-thumb{box-shadow:0 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border);-webkit-appearance:none;margin-top:-7px}input[type=range]:focus::-webkit-slider-runnable-track{background:#efefef;background:var(--background)}input[type=range]::-moz-range-track{width:100%;height:9.5px;-moz-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}input[type=range]::-moz-range-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}input[type=range]::-ms-track{width:100%;height:9.5px;background:transparent;border-color:transparent;border-width:16px 0;color:transparent}input[type=range]::-ms-fill-lower,input[type=range]::-ms-fill-upper{background:#efefef;background:var(--background);border:.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d}input[type=range]::-ms-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;border:1px solid #000;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}input[type=range]:focus::-ms-fill-lower,input[type=range]:focus::-ms-fill-upper{background:#efefef;background:var(--background)}a{text-decoration:none;color:#0076d1;color:var(--links)}a:hover{text-decoration:underline}code,samp,time{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}pre>code{padding:10px;display:block;overflow-x:auto}var{color:#39a33c;color:var(--variable);font-style:normal;font-family:monospace}kbd{background:#efefef;background:var(--background);border:1px solid #dbdbdb;border:1px solid var(--border);border-radius:2px;color:#363636;color:var(--text-main);padding:2px 4px}img,video{max-width:100%;height:auto}hr{border:none;border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}table{border-collapse:collapse;margin-bottom:10px;width:100%;table-layout:fixed}table caption,td,th{text-align:left}td,th{padding:6px;vertical-align:top;word-wrap:break-word}thead{border-bottom:1px solid #dbdbdb;border-bottom:1px solid var(--border)}tfoot{border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}tbody tr:nth-child(2n){background-color:#f7f7f7;background-color:var(--background-alt)}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;background:var(--background);border-radius:6px}::-webkit-scrollbar-thumb{background:#d5d5d5;background:var(--scrollbar-thumb);border-radius:6px}::-webkit-scrollbar-thumb:hover{background:#c4c4c4;background:var(--scrollbar-thumb-hover)}::-moz-selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}::selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}details{display:flex;flex-direction:column;align-items:flex-start;background-color:#f7f7f7;background-color:var(--background-alt);padding:10px 10px 0;margin:1em 0;border-radius:6px;overflow:hidden}details[open]{padding:10px}details>:last-child{margin-bottom:0}details[open] summary{margin-bottom:10px}summary{display:list-item;background-color:#efefef;background-color:var(--background);padding:10px;margin:-10px -10px 0;cursor:pointer;outline:none}summary:focus,summary:hover{text-decoration:underline}details>:not(summary){margin-top:0}summary::-webkit-details-marker{color:#363636;color:var(--text-main)}footer{border-top:1px solid #dbdbdb;border-top:1px solid var(--border);padding-top:10px;color:#70777f;color:var(--text-muted)}body>footer{margin-top:40px}@media print{body,button,code,details,input,pre,summary,textarea{background-color:#fff}button,input,textarea{border:1px solid #000}body,button,code,footer,h1,h2,h3,h4,h5,h6,input,pre,strong,summary,textarea{color:#000}summary::marker{color:#000}summary::-webkit-details-marker{color:#000}tbody tr:nth-child(2n){background-color:#f2f2f2}a{color:#00f;text-decoration:underline}}
--- /dev/null
+<IfModule mod_rewrite.c>
+ RewriteEngine on
+
+ #RewriteBase "/relative/path"
+
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+
+ RewriteRule ^(\d{4})/(\d{2})/(\d{2})(|/(\S{4}))$ index.php?y=$1&m=$2&d=$3&id=$5 [L]
+ RewriteRule ^(\d{4})/(\d{2})$ index.php?y=$1&m=$2 [L]
+ RewriteRule ^(\d{4})$ index.php?y=$1 [L]
+ RewriteRule ^new$ index.php?p=new [L]
+</IfModule>
--- /dev/null
+<?php
+/**
+ * scientia
+ *
+ * Copyright 2021 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+mb_http_output('UTF-8');
+mb_internal_encoding('UTF-8');
+ini_set('error_reporting',-1); // E_ALL & E_STRICT
+
+## check request
+$_urlToParse = filter_var($_SERVER['QUERY_STRING'],FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
+if(!empty($_urlToParse)) {
+ # see http://de2.php.net/manual/en/regexp.reference.unicode.php
+ if(preg_match('/[\p{C}\p{M}\p{Sc}\p{Sk}\p{So}\p{Zl}\p{Zp}]/u',$_urlToParse) === 1) {
+ die('Malformed request. Make sure you know what you are doing.');
+ }
+}
+
+## config
+require_once('config/config.php');
+
+## set the error reporting
+ini_set('log_errors',true);
+ini_set('error_log',PATH_SYSTEMOUT.'/error.log');
+if(DEBUG === true) {
+ ini_set('display_errors',true);
+}
+else {
+ ini_set('display_errors',false);
+}
+
+# time settings
+date_default_timezone_set(TIMEZONE);
+
+# required libs
+require_once('lib/summoner.class.php');
+
+Summoner::simpleAuth();
+
+# database object
+$DB = false;
+
+## DB connection
+$DB = new mysqli(DB_HOST, DB_USERNAME,DB_PASSWORD, DB_NAME);
+if ($DB->connect_errno) exit('Can not connect to MySQL Server');
+$DB->set_charset("utf8mb4");
+$DB->query("SET collation_connection = 'utf8mb4_unicode_ci'");
+$driver = new mysqli_driver();
+$driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
+
+# default values
+$_view = 'list';
+$_year = date('Y');
+$_month = date('m');
+$_day = date('d');
+$_id = false;
+$_requestDateProvided = '';
+$TemplateData = array();
+
+if(isset($_GET['y']) && Summoner::validate($_GET['y'], 'digit')) {
+ $_year = trim($_GET['y']);
+ $_requestDateProvided .= 'y';
+}
+if(isset($_GET['m']) && Summoner::validate($_GET['m'], 'digit')) {
+ $_month = trim($_GET['m']);
+ $_requestDateProvided .= 'm';
+}
+if(isset($_GET['d']) && Summoner::validate($_GET['d'], 'digit')) {
+ $_day = trim($_GET['d']);
+ $_requestDateProvided .= 'd';
+}
+if(isset($_GET['p']) && Summoner::validate($_GET['p'], 'nospace') && $_GET['p'] == "new") {
+ $_view = 'entry';
+}
+if(isset($_GET['id']) && Summoner::validate($_GET['id'], 'nospace',4)) {
+ $_id = trim($_GET['id']);
+ $_view = 'entry';
+}
+
+try {
+ $_date = new DateTime("$_year-$_month-$_day");
+} catch (Exception $e) {
+ $_date = new DateTime();
+}
+
+require_once 'view/'.$_view.'/'.$_view.'.php';
+
+# header information
+header('Content-type: text/html; charset=UTF-8');
+if(isset($TemplateData['refresh']) && !empty($TemplateData['refresh'])) {
+ header('Location: '.PATH_WEBROOT.$TemplateData['refresh']);
+ exit();
+}
+
+require_once 'view/_head.php';
+require_once 'view/'.$_view.'/'.$_view.'.html';
+require_once 'view/_foot.php';
+
+$DB->close();
--- /dev/null
+<?php
+
+/**
+ * Class Entry
+ *
+ * Entry loading and creation
+ */
+class Entry {
+ /**
+ * the global DB object
+ *
+ * @var mysqli
+ */
+ private $_DB;
+
+ /**
+ * Entry constructor.
+ *
+ * @param mysqli $db
+ */
+ public function __construct($db) {
+ $this->_DB = $db;
+ }
+
+ /**
+ * Create a new entry with given data
+ * Data is not validated anymore
+ *
+ * @param string $data
+ * @return mixed
+ */
+ public function create($data) {
+ $ret = false;
+
+ $_words = implode(' ', $this->_words($data));
+ $_ident = Summoner::b64sl_pack_id(rand(111111, 999999));
+ $queryStr = "INSERT INTO `".DB_PREFIX."_entry` SET
+ `created` = NOW(),
+ `date` = CURRENT_DATE(),
+ `ident` = '".$this->_DB->real_escape_string($_ident)."',
+ `body` = '".$this->_DB->real_escape_string($data)."',
+ `words` = '".$this->_DB->real_escape_string($_words)."'";
+ if(QUERY_DEBUG) error_log("[QUERY] ".__METHOD__." query: ".var_export($queryStr,true));
+
+ try {
+ $this->_DB->query($queryStr);
+ $ret = $_ident;
+ }
+ catch(Exception $e) {
+ error_log("[ERROR] ".__METHOD__." catch: ".$e->getMessage());
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Load an entry by given $id. Use date info to make sure that the context is correct
+ *
+ * @param string $y Year Y
+ * @param string $m Month m
+ * @param string $d Day d
+ * @param string $id Id of the entry
+ * @return array|null
+ */
+ public function load($y, $m, $d, $id) {
+ $ret = array();
+
+ if(!empty($id) && !empty($y) && !empty($m) && !empty($d)) {
+ $queryStr = "SELECT `created`,`modified`,`body`
+ FROM `".DB_PREFIX."_entry`
+ WHERE `ident` = '".$this->_DB->real_escape_string($id)."'
+ AND `date` = '".$this->_DB->real_escape_string($y.'-'.$m.'-'.$d)."'";
+ if(QUERY_DEBUG) error_log("[QUERY] ".__METHOD__." query: ".var_export($queryStr,true));
+ try {
+ $query = $this->_DB->query($queryStr);
+ if($query !== false && $query->num_rows > 0) {
+ $ret = $query->fetch_assoc();
+ }
+ }
+ catch(Exception $e) {
+ error_log("[ERROR] ".__METHOD__." catch: ".$e->getMessage());
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Update an entry by given $id and $data
+ *
+ * @param array $data
+ * @param string $id
+ * @return mixed
+ */
+ public function update($data,$id) {
+ $ret = false;
+
+ if(!empty($data) && !empty($id)) {
+ $_words = implode(' ', $this->_words($data));
+ $queryStr = "UPDATE `".DB_PREFIX."_entry` SET
+ `body` = '".$this->_DB->real_escape_string($data)."',
+ `words` = '".$this->_DB->real_escape_string($_words)."'
+ WHERE `ident` = '".$this->_DB->real_escape_string($id)."'";
+ if(QUERY_DEBUG) error_log("[QUERY] ".__METHOD__." query: ".var_export($queryStr,true));
+ try {
+ $this->_DB->query($queryStr);
+ $ret = $id;
+ }
+ catch(Exception $e) {
+ error_log("[ERROR] ".__METHOD__." catch: ".$e->getMessage());
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Create unique words from the given data
+ *
+ * @todo ignores
+ *
+ * @param $data
+ * @return array
+ */
+ private function _words($data) {
+ preg_match_all('/\w{3,}+/',$data,$matches);
+ return array_unique($matches[0]);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Class Summoner
+ *
+ * A static helper class
+ */
+class Summoner {
+ /**
+ * validate the given string with the given type. Optional check the string
+ * length
+ *
+ * @param string $input The string to check
+ * @param string $mode How the string should be checked
+ * @param mixed $limit If int given the string is checked for length
+ *
+ * @return bool
+ *
+ * @see http://de.php.net/manual/en/regexp.reference.unicode.php
+ * http://www.sql-und-xml.de/unicode-database/#pc
+ *
+ * the pattern replaces all that is allowed. the correct result after
+ * the replace should be empty, otherwise are there chars which are not
+ * allowed
+ */
+ static function validate($input,$mode='text',$limit=false) {
+ // check if we have input
+ $input = trim($input);
+
+ if($input == "") return false;
+
+ $ret = false;
+
+ switch ($mode) {
+ case 'mail':
+ if(filter_var($input,FILTER_VALIDATE_EMAIL) === $input) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ break;
+
+ case 'url':
+ if(filter_var($input,FILTER_VALIDATE_URL) === $input) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ break;
+
+ case 'nospace':
+ // text without any whitespace and special chars
+ $pattern = '/[\p{L}\p{N}]/u';
+ break;
+
+ case 'nospaceP':
+ // text without any whitespace and special chars
+ // but with Punctuation other
+ # http://www.sql-und-xml.de/unicode-database/po.html
+ $pattern = '/[\p{L}\p{N}\p{Po}\-]/u';
+ break;
+
+ case 'digit':
+ // only numbers and digit
+ // warning with negative numbers...
+ $pattern = '/[\p{N}\-]/';
+ break;
+
+ case 'pageTitle':
+ // text with whitespace and without special chars
+ // but with Punctuation
+ $pattern = '/[\p{L}\p{N}\p{Po}\p{Z}\s-]/u';
+ break;
+
+ # strange. the \p{M} is needed.. don't know why..
+ case 'filename':
+ $pattern = '/[\p{L}\p{N}\p{M}\-_\.\p{Zs}]/u';
+ break;
+
+ case 'text':
+ default:
+ $pattern = '/[\p{L}\p{N}\p{P}\p{S}\p{Z}\p{M}\s]/u';
+ }
+
+ $value = preg_replace($pattern, '', $input);
+
+ if($value === "") {
+ $ret = true;
+ }
+
+ if(!empty($limit)) {
+ # isset starts with 0
+ if(isset($input[$limit])) {
+ # too long
+ $ret = false;
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * check if a string starts with a given string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @return boolean
+ */
+ static function startsWith($haystack, $needle) {
+ $length = strlen($needle);
+ return (substr($haystack, 0, $length) === $needle);
+ }
+
+ /**
+ * check if a string ends with a given string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @return boolean
+ */
+ static function endsWith($haystack, $needle) {
+ $length = strlen($needle);
+ if ($length == 0) {
+ return true;
+ }
+
+ return (substr($haystack, -$length) === $needle);
+ }
+
+
+ /**
+ * create a short string based on a integer
+ *
+ * @see https://www.jwz.org/base64-shortlinks/
+ * @param int $id
+ * @return string
+ */
+ static function b64sl_pack_id($id) {
+ error_log($id);
+ $id = intval($id);
+ $ida = ($id > 0xFFFFFFFF ? $id >> 32 : 0); // 32 bit big endian, top
+ $idb = ($id & 0xFFFFFFFF); // 32 bit big endian, bottom
+ $id = pack ('N', $ida) . pack ('N', $idb);
+ $id = preg_replace('/^\000+/', '', "$id"); // omit high-order NUL bytes
+ $id = base64_encode ($id);
+ $id = str_replace ('+', '-', $id); // encode URL-unsafe "+" "/"
+ $id = str_replace ('/', '_', $id);
+ $id = preg_replace ('/=+$/', '', $id); // omit trailing padding bytes
+ return $id;
+ }
+
+ /**
+ * Decode a base64-encoded big-endian integer of up to 64 bits.
+ *
+ * @see https://www.jwz.org/base64-shortlinks/
+ * @param int $id
+ * @return false|int|string|string[]
+ */
+ static function b64sl_unpack_id($id) {
+ $id = str_replace ('-', '+', $id); // decode URL-unsafe "+" "/"
+ $id = str_replace ('_', '/', $id);
+ $id = base64_decode ($id);
+ while (strlen($id) < 8) { $id = "\000$id"; } // pad with leading NULs
+ $a = unpack ('N*', $id); // 32 bit big endian
+ $id = ($a[1] << 32) | $a[2]; // pack top and bottom word
+ return $id;
+ }
+
+ /**
+ * simulate the Null coalescing operator in php5
+ *
+ * this only works with arrays and checking if the key is there and echo/return it.
+ *
+ * http://php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op
+ *
+ * @param $array
+ * @param $key
+ * @return bool|mixed
+ */
+ static function ifset($array,$key) {
+ return isset($array[$key]) ? $array[$key] : false;
+ }
+
+ /**
+ * a very simple HTTP_AUTH authentication.
+ * Needs FRONTEND_USERNAME and FRONTEND_PASSWORD defined
+ */
+ static function simpleAuth() {
+ if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])
+ || $_SERVER['PHP_AUTH_USER'] !== FRONTEND_USERNAME || $_SERVER['PHP_AUTH_PW'] !== FRONTEND_PASSWORD
+ ) {
+ header('WWW-Authenticate: Basic realm="Protected area"');
+ header('HTTP/1.0 401 Unauthorized');
+ echo 'No Access.';
+ exit;
+ }
+ }
+}
--- /dev/null
+</body>
+</html>
--- /dev/null
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/light.min.css">
+ <style type=text/css>
+ body {
+ max-width: 90%;
+ }
+ </style>
+</head>
+<body>
--- /dev/null
+<?php if(!empty($TemplateData['data'])) { ?>
+<p>Created: <?php echo Summoner::ifset($TemplateData['data'],'created'); ?>, Updated: <?php echo Summoner::ifset($TemplateData['data'],'modified'); ?></p>
+<?php } ?>
+<form method="post">
+ <textarea rows="25" placeholder="write here" name="fdata[entry]"><?php echo Summoner::ifset($TemplateData['data'],'body'); ?></textarea>
+ <input type="submit" name="submitForm" value="Save">
+
+</form>
+<p>
+<?php if(!empty($TemplateData['data'])) { ?>
+<a href="<?php echo PATH_WEBROOT; ?>/new">New</a><br />
+<?php } ?>
+<a href="<?php echo PATH_WEBROOT; ?>"><- back</a>
+</p>
--- /dev/null
+<?php
+
+require_once 'lib/entry.class.php';
+$Entry = new Entry($DB);
+
+$TemplateData['data'] = '';
+if(!empty($_id)) {
+ $TemplateData['data'] = $Entry->load($_year,$_month,$_day,$_id);
+}
+
+if(isset($_POST['submitForm']) && isset($_POST['fdata'])) {
+ $fdata = $_POST['fdata'];
+ if(isset($fdata['entry']) && Summoner::validate($fdata['entry'])) {
+ $_dataToSave = trim($fdata['entry']);
+
+ if(!empty($_id)) {
+ $do = $Entry->update($_dataToSave,$_id);
+ $_r = '/'.$_year.'/'.$_month.'/'.$_day.'/'.$_id;
+ }
+ else {
+ $do = $Entry->create($_dataToSave);
+ $_r = date('/Y/m/d/').$do;;
+ }
+
+ if($do !== false) {
+ $TemplateData['refresh'] = $_r;
+ }
+ }
+}
--- /dev/null
+<?php if(!empty($TemplateData['entries'])) { ?>
+<?php
+ foreach($TemplateData['entries'] as $gk=>$g) {
+ echo $gk;
+?>
+<ul>
+ <?php foreach($g as $e) { ?>
+ <li><a href="<?php echo $e['link']; ?>"><?php echo $e['ident']; ?></a> <?php echo $e['date']; ?> <?php echo htmlspecialchars($e['body'],ENT_HTML5); ?></li>
+ <?php } ?>
+</ul>
+<?php
+ }
+}
+?>
--- /dev/null
+<?php
+$TemplateData['entries'] = array();
+
+$queryStr = "SELECT `e`.`ident`, `e`.`date`, SUBSTRING(`e`.`body`,1,100) AS body FROM `".DB_PREFIX."_entry` AS e";
+$queryLimit = " LIMIT 100";
+$groupByFormat = $_date->format('Y');
+if(!empty($_requestDateProvided)) {
+ $_intervalStart = false;
+ $_intervalEnd = false;
+
+ if($_requestDateProvided === 'ymd') {
+ $_intervalStart = new DateInterval('P1D');
+ $_intervalEnd = new DateInterval('P2D');
+ $queryLimit = "";
+ $groupByFormat = $_date->format('Y-m-d');
+ }
+ elseif ($_requestDateProvided === 'ym') {
+ $_intervalStart = new DateInterval('P1M');
+ $_intervalEnd = new DateInterval('P2M');
+ $queryLimit = "";
+ $groupByFormat = $_date->format('Y-m');
+ }
+ elseif ($_requestDateProvided === 'y') {
+ $_intervalStart = new DateInterval('P1Y');
+ $_intervalEnd = new DateInterval('P2Y');
+ }
+
+ if(!empty($_intervalStart) && !empty($_intervalEnd)) {
+
+ $_date->sub($_intervalStart);
+ $_f = $_date->format("Y-m-d");
+ $_date->add($_intervalEnd);
+ $_e = $_date->format("Y-m-d");
+
+ $queryStr .= " WHERE `date` >= '".$_f."' AND `date` <= '".$_e."'";
+ }
+}
+
+$queryStr .= " ORDER BY `created` DESC";
+$queryStr .= $queryLimit;
+if(QUERY_DEBUG) error_log("[QUERY] query: ".var_export($queryStr,true));
+
+try {
+ $query = $DB->query($queryStr);
+ if($query !== false && $query->num_rows > 0) {
+ while(($result = $query->fetch_assoc()) != false) {
+ $_d = new DateTime($result['date']);
+ $TemplateData['entries'][$_d->format($groupByFormat)][$result['ident']] = $result;
+ $TemplateData['entries'][$_d->format($groupByFormat)][$result['ident']]['link'] = str_replace('-','/',$result['date']).'/'.$result['ident'];
+ }
+ }
+}
+catch(Exception $e) {
+ error_log("[ERROR] catch: ".$e->getMessage());
+}
--- /dev/null
+:root{--background-body:#fff;--background:#efefef;--background-alt:#f7f7f7;--selection:#9e9e9e;--text-main:#363636;--text-bright:#000;--text-muted:#70777f;--links:#0076d1;--focus:rgba(0,150,191,0.67);--border:#dbdbdb;--code:#000;--animation-duration:0.1s;--button-hover:#ddd;--scrollbar-thumb:#d5d5d5;--scrollbar-thumb-hover:#c4c4c4;--form-placeholder:#949494;--form-text:#000;--variable:#39a33c;--highlight:#ff0;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E")}html{scrollbar-color:#d5d5d5 #fff;scrollbar-color:var(--scrollbar-thumb) var(--background-body);scrollbar-width:thin}body{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Segoe UI Emoji,Apple Color Emoji,Noto Color Emoji,sans-serif;line-height:1.4;max-width:800px;margin:20px auto;padding:0 10px;word-wrap:break-word;color:#363636;color:var(--text-main);background:#fff;background:var(--background-body);text-rendering:optimizeLegibility}button,input,textarea{transition:background-color .1s linear,border-color .1s linear,color .1s linear,box-shadow .1s linear,transform .1s ease;transition:background-color var(--animation-duration) linear,border-color var(--animation-duration) linear,color var(--animation-duration) linear,box-shadow var(--animation-duration) linear,transform var(--animation-duration) ease}h1{font-size:2.2em;margin-top:0}h1,h2,h3,h4,h5,h6{margin-bottom:12px;margin-top:24px}h1,h2,h3,h4,h5,h6,strong{color:#000;color:var(--text-bright)}b,h1,h2,h3,h4,h5,h6,strong,th{font-weight:600}q:after,q:before{content:none}blockquote,q{border-left:4px solid rgba(0,150,191,.67);border-left:4px solid var(--focus);margin:1.5em 0;padding:.5em 1em;font-style:italic}blockquote>footer{font-style:normal;border:0}address,blockquote cite{font-style:normal}a[href^=mailto\:]:before{content:"📧 "}a[href^=tel\:]:before{content:"📞 "}a[href^=sms\:]:before{content:"💬 "}mark{background-color:#ff0;background-color:var(--highlight);border-radius:2px;padding:0 2px;color:#000}button,input[type=button],input[type=checkbox],input[type=radio],input[type=range],input[type=submit],select{cursor:pointer}input:not([type=checkbox]):not([type=radio]),select{display:block}button,input,select,textarea{color:#000;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}input[type=checkbox],input[type=radio]{height:1em;width:1em}input[type=radio]{border-radius:100%}input{vertical-align:top}label{vertical-align:middle;margin-bottom:4px;display:inline-block}button,input:not([type=checkbox]):not([type=radio]),input[type=range],select,textarea{-webkit-appearance:none}textarea{display:block;margin-right:0;box-sizing:border-box;resize:vertical}textarea:not([cols]){width:100%}textarea:not([rows]){min-height:40px;height:140px}select{background:#efefef url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='63' width='117' fill='%23161f27'%3E%3Cpath d='M115 2c-1-2-4-2-5 0L59 53 7 2a4 4 0 00-5 5l54 54 2 2 3-2 54-54c2-1 2-4 0-5z'/%3E%3C/svg%3E") calc(100% - 12px) 50%/12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50%/12px no-repeat;padding-right:35px}select::-ms-expand{display:none}select[multiple]{padding-right:10px;background-image:none;overflow-y:auto}button,input[type=button],input[type=submit]{padding-right:30px;padding-left:30px}button:hover,input[type=button]:hover,input[type=submit]:hover{background:#ddd;background:var(--button-hover)}button:focus,input:focus,select:focus,textarea:focus{box-shadow:0 0 0 2px rgba(0,150,191,.67);box-shadow:0 0 0 2px var(--focus)}button:active,input[type=button]:active,input[type=checkbox]:active,input[type=radio]:active,input[type=range]:active,input[type=submit]:active{transform:translateY(2px)}button:disabled,input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;opacity:.5}::-moz-placeholder{color:#949494;color:var(--form-placeholder)}:-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::placeholder{color:#949494;color:var(--form-placeholder)}fieldset{border:1px solid rgba(0,150,191,.67);border:1px solid var(--focus);border-radius:6px;margin:0 0 12px;padding:10px}legend{font-size:.9em;font-weight:600}input[type=range]{margin:10px 0;padding:10px 0;background:transparent}input[type=range]:focus{outline:none}input[type=range]::-webkit-slider-runnable-track{width:100%;height:9.5px;-webkit-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}input[type=range]::-webkit-slider-thumb{box-shadow:0 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border);-webkit-appearance:none;margin-top:-7px}input[type=range]:focus::-webkit-slider-runnable-track{background:#efefef;background:var(--background)}input[type=range]::-moz-range-track{width:100%;height:9.5px;-moz-transition:.2s;transition:.2s;background:#efefef;background:var(--background);border-radius:3px}input[type=range]::-moz-range-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}input[type=range]::-ms-track{width:100%;height:9.5px;background:transparent;border-color:transparent;border-width:16px 0;color:transparent}input[type=range]::-ms-fill-lower,input[type=range]::-ms-fill-upper{background:#efefef;background:var(--background);border:.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d}input[type=range]::-ms-thumb{box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;border:1px solid #000;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}input[type=range]:focus::-ms-fill-lower,input[type=range]:focus::-ms-fill-upper{background:#efefef;background:var(--background)}a{text-decoration:none;color:#0076d1;color:var(--links)}a:hover{text-decoration:underline}code,samp,time{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}pre>code{padding:10px;display:block;overflow-x:auto}var{color:#39a33c;color:var(--variable);font-style:normal;font-family:monospace}kbd{background:#efefef;background:var(--background);border:1px solid #dbdbdb;border:1px solid var(--border);border-radius:2px;color:#363636;color:var(--text-main);padding:2px 4px}img,video{max-width:100%;height:auto}hr{border:none;border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}table{border-collapse:collapse;margin-bottom:10px;width:100%;table-layout:fixed}table caption,td,th{text-align:left}td,th{padding:6px;vertical-align:top;word-wrap:break-word}thead{border-bottom:1px solid #dbdbdb;border-bottom:1px solid var(--border)}tfoot{border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}tbody tr:nth-child(2n){background-color:#f7f7f7;background-color:var(--background-alt)}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;background:var(--background);border-radius:6px}::-webkit-scrollbar-thumb{background:#d5d5d5;background:var(--scrollbar-thumb);border-radius:6px}::-webkit-scrollbar-thumb:hover{background:#c4c4c4;background:var(--scrollbar-thumb-hover)}::-moz-selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}::selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}details{display:flex;flex-direction:column;align-items:flex-start;background-color:#f7f7f7;background-color:var(--background-alt);padding:10px 10px 0;margin:1em 0;border-radius:6px;overflow:hidden}details[open]{padding:10px}details>:last-child{margin-bottom:0}details[open] summary{margin-bottom:10px}summary{display:list-item;background-color:#efefef;background-color:var(--background);padding:10px;margin:-10px -10px 0;cursor:pointer;outline:none}summary:focus,summary:hover{text-decoration:underline}details>:not(summary){margin-top:0}summary::-webkit-details-marker{color:#363636;color:var(--text-main)}footer{border-top:1px solid #dbdbdb;border-top:1px solid var(--border);padding-top:10px;color:#70777f;color:var(--text-muted)}body>footer{margin-top:40px}@media print{body,button,code,details,input,pre,summary,textarea{background-color:#fff}button,input,textarea{border:1px solid #000}body,button,code,footer,h1,h2,h3,h4,h5,h6,input,pre,strong,summary,textarea{color:#000}summary::marker{color:#000}summary::-webkit-details-marker{color:#000}tbody tr:nth-child(2n){background-color:#f2f2f2}a{color:#00f;text-decoration:underline}}