]> 91.132.146.200 Git - scientia.git/commitdiff
first files. Working, but not usable
authorBanana <mail@bananas-playground.net>
Sun, 31 Jan 2021 15:55:00 +0000 (16:55 +0100)
committerBanana <mail@bananas-playground.net>
Sun, 31 Jan 2021 15:55:00 +0000 (16:55 +0100)
21 files changed:
.gitignore [new file with mode: 0644]
CHANGELOG [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
VERSION [new file with mode: 0644]
documentation/installation.txt [new file with mode: 0644]
sources/water.css [new file with mode: 0644]
webroot/.htaccess [new file with mode: 0644]
webroot/config/.gitignore [new file with mode: 0644]
webroot/config/config.php.default [new file with mode: 0644]
webroot/index.php [new file with mode: 0644]
webroot/lib/entry.class.php [new file with mode: 0644]
webroot/lib/summoner.class.php [new file with mode: 0644]
webroot/systemout/.gitignore [new file with mode: 0644]
webroot/view/_foot.php [new file with mode: 0644]
webroot/view/_head.php [new file with mode: 0644]
webroot/view/entry/entry.html [new file with mode: 0644]
webroot/view/entry/entry.php [new file with mode: 0644]
webroot/view/list/list.html [new file with mode: 0644]
webroot/view/list/list.php [new file with mode: 0644]
webroot/view/water.css [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d7bd2f9
--- /dev/null
@@ -0,0 +1,2 @@
+*.idea
+*.iml
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..bd7f602
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,2 @@
+0.5 Lykos -
+       + Initial beta release
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..c1a81fe
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+    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
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..86dba25
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+scientia - cognizance, insight, knowledge 
+scientia utilis - useful knowledge
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..acf27ca
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.5 - Lykos
diff --git a/documentation/installation.txt b/documentation/installation.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sources/water.css b/sources/water.css
new file mode 100644 (file)
index 0000000..4df6042
--- /dev/null
@@ -0,0 +1 @@
+: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}}
diff --git a/webroot/.htaccess b/webroot/.htaccess
new file mode 100644 (file)
index 0000000..301dd68
--- /dev/null
@@ -0,0 +1,13 @@
+<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>
diff --git a/webroot/config/.gitignore b/webroot/config/.gitignore
new file mode 100644 (file)
index 0000000..cde8069
--- /dev/null
@@ -0,0 +1 @@
+*.php
diff --git a/webroot/config/config.php.default b/webroot/config/config.php.default
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/webroot/index.php b/webroot/index.php
new file mode 100644 (file)
index 0000000..f04d5fb
--- /dev/null
@@ -0,0 +1,114 @@
+<?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();
diff --git a/webroot/lib/entry.class.php b/webroot/lib/entry.class.php
new file mode 100644 (file)
index 0000000..e9bb0fb
--- /dev/null
@@ -0,0 +1,129 @@
+<?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]);
+       }
+}
diff --git a/webroot/lib/summoner.class.php b/webroot/lib/summoner.class.php
new file mode 100644 (file)
index 0000000..22195f0
--- /dev/null
@@ -0,0 +1,200 @@
+<?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;
+               }
+       }
+}
diff --git a/webroot/systemout/.gitignore b/webroot/systemout/.gitignore
new file mode 100644 (file)
index 0000000..397b4a7
--- /dev/null
@@ -0,0 +1 @@
+*.log
diff --git a/webroot/view/_foot.php b/webroot/view/_foot.php
new file mode 100644 (file)
index 0000000..308b1d0
--- /dev/null
@@ -0,0 +1,2 @@
+</body>
+</html>
diff --git a/webroot/view/_head.php b/webroot/view/_head.php
new file mode 100644 (file)
index 0000000..a109da2
--- /dev/null
@@ -0,0 +1,11 @@
+<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>
diff --git a/webroot/view/entry/entry.html b/webroot/view/entry/entry.html
new file mode 100644 (file)
index 0000000..0e956c0
--- /dev/null
@@ -0,0 +1,14 @@
+<?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>
diff --git a/webroot/view/entry/entry.php b/webroot/view/entry/entry.php
new file mode 100644 (file)
index 0000000..a3ab775
--- /dev/null
@@ -0,0 +1,29 @@
+<?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;
+               }
+       }
+}
diff --git a/webroot/view/list/list.html b/webroot/view/list/list.html
new file mode 100644 (file)
index 0000000..36ef809
--- /dev/null
@@ -0,0 +1,14 @@
+<?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
+       }
+}
+?>
diff --git a/webroot/view/list/list.php b/webroot/view/list/list.php
new file mode 100644 (file)
index 0000000..0ef3dd6
--- /dev/null
@@ -0,0 +1,55 @@
+<?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());
+}
diff --git a/webroot/view/water.css b/webroot/view/water.css
new file mode 100644 (file)
index 0000000..4df6042
--- /dev/null
@@ -0,0 +1 @@
+: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}}