1
0
Fork 0

First release

This commit is contained in:
Airikr 2024-04-25 21:55:08 +02:00
parent 4f2f145c82
commit 3c8e79545d
35 changed files with 1397 additions and 1 deletions

1
.gitignore vendored Executable file
View file

@ -0,0 +1 @@
*.sync.ffs_db

42
.htaccess Executable file
View file

@ -0,0 +1,42 @@
SetEnv SERVER_ADMIN hi@domain.tld
SetEnv TZ Europe/Stockholm
DefaultLanguage sv-SE
AddDefaultCharset UTF-8
Options All -Indexes
IndexIgnore *
LimitRequestBody 10240000
<Files .htaccess>
order allow,deny
deny from all
</Files>
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
Header always set X-Frame-Options "SAMEORIGIN"
#Header always set Content-Security-Policy "default-src 'self'; img-src 'self'"
Header always set X-Frame-Options "ALLOW-FROM URL"
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy "same-origin"
Header always set Permissions-Policy "encrypted-media=(),fullscreen=*"
</IfModule>
<IfModule mod_rewrite.c>
DirectoryIndex index.php
ErrorDocument 403 /template/page-errors.php?err=403
ErrorDocument 404 /template/page-errors.php?err=404
ErrorDocument 500 /template/page-errors.php?err=500
RewriteEngine On
RewriteBase /template/
RewriteCond %{REQUEST_METHOD} !^(GET|POST)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$ index.php
</IfModule>

View file

@ -1,2 +1,3 @@
# template
The standard set-up for all my website projects.
Run `composer install` to install the associated functions.

11
composer.json Executable file
View file

@ -0,0 +1,11 @@
{
"require": {
"erusev/parsedown": "^1.7",
"particle/validator": "^2.3",
"matthiasmullie/minify": "^1.3",
"whichbrowser/parser": "^2.1",
"pragmarx/google2fa": "^8.0",
"paragonie/halite": "^5",
"phpmailer/phpmailer": "^6.8"
}
}

527
css/desktop.css Executable file
View file

@ -0,0 +1,527 @@
@font-face {
font-family: 'Inter Tight';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../../fonts/inter-tight-400.woff2);
unicode-range: U+000-5FF;
}
@font-face {
font-family: 'Inter Tight';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../../fonts/inter-tight-700.woff2);
unicode-range: U+000-5FF;
}
/* Variables for the universal theme */
:root {
--main: #272e33;
--text: #e8e5d5;
--link_focused: #2e383c;
--line: #475258;
--form_bg: #2e383c;
--field_bg: #1e2326;
--field_border: #414b50;
--field_border_focused: #9da9a0;
--submit_bg: #7fbbb3;
--submit_text: #1e2326;
--red: #e67e80;
--red_underline: #613537;
--green: #a7c080;
--blue: #7fbbb3;
--yellow: #dbbc7f;
--orange: #E69875;
--icon_select: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-selector" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="rgba(255,255,255,1)" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 9l4 -4l4 4"></path><path d="M16 15l-4 4l-4 -4"></path></svg>');
--font: 'Inter Tight', monospace;
--font_mono: 'Inter Tight', monospace;
--fontsize: 1rem;
--lineheight: 1.75rem;
}
* {
box-sizing: content-box;
scroll-behavior: smooth;
}
html, body {
background-color: var(--main);
color: var(--text);
font-family: var(--font);
font-size: var(--fontsize);
line-height: var(--lineheight);
margin: 0;
padding: 0;
}
a {
color: var(--text);
text-decoration: underline;
text-decoration-color: var(--line);
text-decoration-thickness: .05rem;
/* text-decoration-style: wavy; */
text-underline-offset: 5px;
}
a.color-red {
text-decoration-color: var(--red_underline);
}
p {
hyphens: auto;
margin: 0;
padding: 10px 0;
text-align: justify;
word-wrap: break-word;
-moz-hyphens: auto;
-webkit-hyphens: auto;
-o-hyphens: auto;
}
mark {
background-color: var(--mark);
color: var(--text);
}
ul {
margin: 0 0 0 30px;
padding: 5px 0;
}
ul > li {
padding: 5px 0;
}
ul > li > a > svg {
height: 20px;
width: 20px;
}
ul > li > a > svg > path:last-child {
fill: var(--text);
}
ul > li > ul {
margin: 0 0 0 20px;
}
ol {
list-style-type: none;
counter-reset: item;
margin: 0 0 0 30px;
padding: 5px 0;
}
ol > li {
display: table;
counter-increment: item;
padding: 5px 0;
}
ol > li > div {
padding: 5px 0;
}
ol > li:before {
content: counters(item, ".");
display: table-cell;
font-weight: 700;
width: 25px;
}
ol > li > ol {
margin: 0;
}
ol > li > ol > li:before {
content: counters(item, ".");
width: 40px;
}
ol > li > ol.second > li > ol.third > li:before {
width: 50px;
}
ol.third {
margin-bottom: -5px;
}
input:not([type="checkbox"]),
textarea,
select {
background-color: var(--field_bg);
border: 1px solid var(--field_border);
border-radius: 3px;
color: var(--text);
font-family: var(--font);
font-size: var(--fontsize);
outline: none;
resize: none;
padding: 5px;
width: calc(100% - (6px * 2));
}
input:not([type="checkbox"]):focus,
textarea:focus,
select:focus {
border: 1px solid var(--field_border_focused);
}
input[disabled],
textarea[disabled],
select[disabled] {
background-color: var(--main);
border: 1px dashed var(--field_border);
cursor: not-allowed;
}
input[type="submit"] {
background-color: var(--submit_bg);
border: 1px solid var(--submit_bg);
color: var(--submit_text);
cursor: pointer;
font-weight: 700;
padding: 5px 10px;
width: auto;
}
input[type="radio"] {
cursor: pointer;
line-height: 100%;
opacity: 0;
position: absolute;
width: auto;
}
input[type="radio"] + label {
border: 1px solid transparent;
cursor: pointer;
margin: 0 3px;
opacity: .7;
padding: 1px 3px;
}
input[type="radio"]:checked + label {
background-color: var(--checked);
backdrop-filter: blur(3px);
border-radius: 2px;
color: var(--checked_str);
opacity: 1;
}
input[type="radio"]:checked:focus + label {
border: 1px solid var(--checked_focus);
}
input[type="date"] {
appearance: none;
}
input, textarea {
caret-color: var(--yellow);
}
textarea {
height: 100px;
width: calc(100% - 12px);
}
select {
appearance: none;
background-image: var(--icon_select);
background-size: 17px;
background-repeat: no-repeat;
background-position: center right 8px;
cursor: pointer;
padding: 5px;
width: calc(100% - (6px * 2) + 12px);
}
h1 {
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-size: 190%;
font-weight: 700;
margin: 0 0 5px 0;
line-height: 2.5rem;
padding: 0;
}
h1 > svg {
margin: 0 5px;
opacity: .4;
width: 32px;
}
h2 {
font-size: 140%;
font-weight: 700;
margin: 30px 0 0 0;
padding: 0;
}
hr {
border: 0;
border-top: 1px solid var(--line);
margin: 30px -50px;
padding: 0;
}
sup {
vertical-align: top;
}
figure {
margin-block-start: 0;
margin-block-end: 0;
margin-inline-start: 0;
margin-inline-end: 0;
margin: 0;
width: 100%;
}
figure,
figure > img {
object-fit: cover;
vertical-align: top;
width: 100%;
}
svg {
height: 100%;
vertical-align: top;
width: 20px;
}
svg[class*="icon-tabler-currency"] {
height: auto;
margin: .10rem .2rem 0 .2rem;
width: 18px;
}
#website {
margin: 50px 80px;
max-width: 1250px;
}
#website > main {
width: 1000px;
}
.color-grey {
opacity: .6;
}
.color-red {
color: var(--red) !important;
}
.color-green {
color: var(--green);
}
.color-blue {
color: var(--blue);
}
.color-yellow {
color: var(--yellow);
}
.message {
font-size: 126%;
font-weight: 400;
opacity: .7;
padding: 20px 10px;
text-align: center;
}
.msg {
display: none;
}
.msg > div {
align-items: flex-start;
display: flex;
flex-direction: row;
font-size: 100%;
margin-bottom: 20px;
padding: 0;
text-align: left;
}
.msg > div > svg {
margin-right: 10px;
}
.mono {
font-family: var(--font_mono) !important;
font-size: 100%;
}
.no-select {
cursor: default;
user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-webkit-user-drag: none;
}
.side-by-side {
align-items: flex-start;
display: flex;
flex-direction: row;
}
.hidden {
display: none !important;
}
.visible {
display: block !important;
}
.checkboxes {
padding: 20px 0;
}
.checkbox:not(:first-child) {
margin-top: 25px;
}
.checkbox.nodesc {
margin-top: 0;
}
.checkbox > div {
align-items: center;
display: inline-flex;
flex-direction: row;
position: relative;
}
.checkbox > div > input {
cursor: pointer !important;
left: 5px;
opacity: 0;
position: absolute;
top: 5px;
}
.checkbox > div > input[disabled],
.checkbox > div > input[disabled] ~ label {
color: var(--checkbox_disabled);
cursor: not-allowed !important;
user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-webkit-user-drag: none;
}
.checkbox > div > input[disabled] ~ .icon-checkbox > svg > path:not(:first-child) {
color: var(--checkbox_disabled);
}
.checkbox > div > .icon-checkbox {
left: 6px;
position: absolute;
pointer-events: none;
top: 5px;
}
.checkbox > div > .icon-checkbox.is-checked,
.checkbox > div > input:checked ~ .icon-checkbox.is-unchecked {
opacity: 0;
}
.checkbox > div > input:checked ~ .is-checked {
opacity: 1;
}
.checkbox > div > label {
cursor: pointer !important;
padding: 4px 8px 4px 35px;
}
.checkbox > div > input:not([disabled]):hover ~ .icon-checkbox,
.checkbox > div > input:not([disabled]):hover ~ label,
.checkbox > div > input:not([disabled]):focus ~ .icon-checkbox,
.checkbox > div > input:not([disabled]):focus ~ label {
background-color: var(--checkbox_focus);
border-radius: 3px;
}
.checkbox > .desc {
display: block;
left: 35px;
line-height: 140%;
font-size: 98%;
opacity: .7;
top: 4px;
width: calc(100% - 35px);
}
.checkbox > .desc > p {
text-align: left;
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

5
css/portable.css Executable file
View file

@ -0,0 +1,5 @@
@media only screen and (max-width: 1409px) {
}

25
functions/checkbox.php Executable file
View file

@ -0,0 +1,25 @@
<?php
function checkbox($string, $id, $desc = null, $variable = null, $disabled = false) {
$content = '<div class="checkbox'.(!empty($desc) ? '' : ' nodesc').'">';
$content .= '<div>';
$content .= '<input type="checkbox" name="check-'.$id.'" id="'.$id.'"';
$content .= ($variable == true ? ' checked' : null);
$content .= ($disabled == false ? null : ' disabled').'>';
$content .= '<div class="icon-checkbox is-unchecked">'.svgicon('unchecked').'</div>';
$content .= '<div class="icon-checkbox is-checked">'.svgicon('checked').'</div>';
$content .= '<label for="'.$id.'">'.$string.'</label>';
$content .= '</div>';
if(!empty($desc)) {
$content .= '<div class="desc">'.$desc.'</div>';
}
$content .= '</div>';
return $content;
}
?>

16
functions/create-folder.php Executable file
View file

@ -0,0 +1,16 @@
<?php
function create_folder($string) {
if(!file_exists($string)) {
if(!is_writeable($string)) {
die(simplepage('Was not able to create folder outside root: permission denied.', false, true));
} else {
$oldmask = umask(0);
mkdir($string, 0777, true);
umask($oldmask);
}
}
}
?>

51
functions/date.php Executable file
View file

@ -0,0 +1,51 @@
<?php
function date_($timestamp, $format) {
global $get_dateformat, $get_daysuffix, $lang;
$months = Array(
1 => 'Januari',
2 => 'Februari',
3 => 'Mars',
4 => 'April',
5 => 'Maj',
6 => 'Juni',
7 => 'Juli',
8 => 'Augusti',
9 => 'September',
10 => 'Oktober',
11 => 'November',
12 => 'December'
);
if($format == 'datetime') {
return date('Y-m-d, H:i', $timestamp);
} elseif($format == 'date') {
return date('Y-m-d', $timestamp);
} elseif($format == 'time') {
return date('H:i', $timestamp);
} elseif($format == 'year') {
return date('Y', $timestamp);
} elseif($format == 'month') {
return $months[date('n', $timestamp)];
} elseif($format == 'day-month') {
return date('j', $timestamp).' '.mb_strtolower($months[date('n', $timestamp)]);
} elseif($format == 'month-year') {
return $months[date('n', $timestamp)].' '.date('Y', $timestamp);
} elseif($format == 'day-month-year') {
return date('j', $timestamp).' '.mb_strtolower($months[date('n', $timestamp)]).', '.date('Y', $timestamp);
} elseif($format == 'day-month-year-time') {
return date('j', $timestamp).' '.mb_strtolower($months[date('n', $timestamp)]).' '.date('Y', $timestamp).', kl. '.date('H:i', $timestamp);
}
}
?>

20
functions/endecrypt-file.php Executable file
View file

@ -0,0 +1,20 @@
<?php
function endecrypt_file($file, $encrypt = true) {
global $enc, $dir_encfiles, $encryption_method;
$encryption_key = base64_decode($enc['keys'][0]);
if($encrypt == true) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($encryption_method));
$encrypted = openssl_encrypt(file_get_contents($dir_encfiles.'/'.$file), $encryption_method, $encryption_key, 0, $iv);
file_put_contents($dir_encfiles.'/'.$file.'.enc', base64_encode($encrypted.'::'.$iv));
} else {
list($encrypted_data, $iv) = explode('::', base64_decode(file_get_contents($dir_encfiles.'/'.$file.'.enc')), 2);
$decrypt = openssl_decrypt($encrypted_data, $encryption_method, $encryption_key, 0, $iv);
file_put_contents($dir_encfiles.'/'.$file, $decrypt);
}
}
?>

37
functions/endecrypt.php Executable file
View file

@ -0,0 +1,37 @@
<?php
use ParagonIE\Halite\File;
use ParagonIE\Halite\KeyFactory;
use ParagonIE\Halite\Symmetric\Crypto as Symmetric;
use ParagonIE\HiddenString\HiddenString;
set_time_limit(300);
function endecrypt($string, $encrypt = true, $file = false) {
global $dir_files, $site_url;
if(!file_exists($dir_files.'/'.hash('sha256', $site_url).'.key')) {
$enckey = KeyFactory::generateEncryptionKey();
KeyFactory::save($enckey, $dir_files.'/'.hash('sha256', $site_url).'.key');
} else {
$enckey = KeyFactory::loadEncryptionKey($dir_files.'/'.hash('sha256', $site_url).'.key');
if($file == false) {
if($encrypt == true) {
return Symmetric::encrypt(new HiddenString($string), $enckey);
} else {
return Symmetric::decrypt($string, $enckey);
}
} else {
if($encrypt == true) {
File::encrypt($string, $string.'.enc', $enckey);
} else {
File::decrypt($string.'.enc', $string, $enckey);
}
}
}
}
?>

7
functions/external-link.php Executable file
View file

@ -0,0 +1,7 @@
<?php
function link_($string, $url) {
return '<a href="'.$url.'" target="_blank" rel="noopener noreferrer">'.$string.'</a>';
}
?>

7
functions/format-number.php Executable file
View file

@ -0,0 +1,7 @@
<?php
function format_number($string, $decimal = 2, $symbol = ',', $thousands = ' ') {
return number_format($string, $decimal, $symbol, $thousands);
}
?>

24
functions/get-ip.php Executable file
View file

@ -0,0 +1,24 @@
<?php
function getip() {
if(isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$client = @$_SERVER['HTTP_CLIENT_IP'];
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER['REMOTE_ADDR'];
if(filter_var($client, FILTER_VALIDATE_IP)) {
$ip = $client;
} elseif(filter_var($forward, FILTER_VALIDATE_IP)) {
$ip = $forward;
} else {
$ip = $remote;
}
return $ip;
}
?>

57
functions/log-action.php Executable file
View file

@ -0,0 +1,57 @@
<?php
function log_action($code, $userid = null, $sessionid = null, $iditem = null, $isexpense = null, $isdebt = null, $isloan = null, $isnotes = null, $istfa_enabled = null, $istfa_disabled = null, $isexporting = null, $isimporting = null, $isdeletedata = null) {
global $user, $session;
sql("INSERT INTO sess_actions(
id_user,
id_session,
id_item,
data_code,
is_expense,
is_debt,
is_loan,
is_notes,
is_tfa_enabled,
is_tfa_disabled,
is_exporting,
is_importing,
is_delete_data,
timestamp_occurred
)
VALUES(
:_iduser,
:_idsession,
:_iditem,
:_code,
:_isexpense,
:_isdebt,
:_isloan,
:_isnotes,
:_istfa_enabled,
:_istfa_disabled,
:_isexporting,
:_isimporting,
:_isdeletedata,
:_occurred
)
", Array(
'_iduser' => (empty($userid) ? (int)$user['id'] : (int)$userid),
'_idsession' => (empty($sessionid) ? (int)$session['id'] : (int)$sessionid),
'_iditem' => (empty($iditem) ? null : (int)$iditem),
'_code' => $code,
'_isexpense' => (empty($isexpense) ? null : (int)$isexpense),
'_isdebt' => (empty($isdebt) ? null : (int)$isdebt),
'_isloan' => (empty($isloan) ? null : (int)$isloan),
'_isnotes' => (empty($isnotes) ? null : (int)$isnotes),
'_istfa_enabled' => (empty($istfa_enabled) ? null : (int)$istfa_enabled),
'_istfa_disabled' => (empty($istfa_disabled) ? null : (int)$istfa_disabled),
'_isexporting' => (empty($isexporting) ? null : (int)$isexporting),
'_isimporting' => (empty($isimporting) ? null : (int)$isimporting),
'_isdeletedata' => (empty($isdeletedata) ? null : (int)$isdeletedata),
'_occurred' => time()
), 'insert');
}
?>

7
functions/lowercase-plus.php Executable file
View file

@ -0,0 +1,7 @@
<?php
function lowercaseplus($string) {
return str_replace(' ', '+', mb_strtolower($string));
}
?>

11
functions/pw-random.php Executable file
View file

@ -0,0 +1,11 @@
<?php
function pw_random($digit = 20) {
$comb = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
$shfl = str_shuffle($comb);
$pwd = substr($shfl, 0, $digit);
return $pwd;
}
?>

7
functions/safe-tag.php Executable file
View file

@ -0,0 +1,7 @@
<?php
function safetag($string) {
return strip_tags(htmlspecialchars($string));
}
?>

50
functions/send-email.php Executable file
View file

@ -0,0 +1,50 @@
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
function send_email($to_email, $subject, $content_html, $content_nohtml) {
global $smtp_host, $smtp_email, $smtp_password, $smtp_port, $config_encoding, $config_email_noreply, $site_title;
$mail = new PHPMailer(true);
try {
$mail->SMTPDebug = SMTP::DEBUG_OFF;
$mail->isSMTP();
$mail->Host = $smtp_host;
$mail->SMTPAuth = true;
$mail->Username = $smtp_email;
$mail->Password = $smtp_password;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = $smtp_port;
$mail->setFrom($config_email_noreply, mb_convert_encoding($site_title, $config_encoding));
$mail->addAddress($to_email, null);
#$mail->addReplyTo('info@example.com', 'Information');
#$mail->addCC('cc@example.com');
#$mail->addBCC('bcc@example.com');
#$mail->addAttachment('/tmp/image.jpg', 'new.jpg');
$mail->isHTML(true);
$mail->Subject = mb_convert_encoding($subject, $config_encoding);
$mail->Body = simplepage(mb_convert_encoding($content_html, $config_encoding));
$mail->AltBody = mb_convert_encoding($content_nohtml, $config_encoding);
$mail->send();
} catch (Exception $e) {
echo 'mail-error';
}
}
function mailcontent($string) {
return simplepage($string);
}
?>

37
functions/simple-page.php Executable file
View file

@ -0,0 +1,37 @@
<?php
function simplepage($string, $is_email = true, $error = false) {
global $site_title, $site_favicon;
$content = '<!DOCTYPE html>';
$content .= '<html lang="sv">';
$content .= '<head>';
$content .= '<title>'.$site_title.' - '.(empty($is_email) ? 'Oops' : 'E-postmeddelande').'</title>';
$content .= '<meta charset="UTF-8">';
$content .= '<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, maximum-scale=3">';
$content .= '<link rel="icon" href="'.$site_favicon.'">';
$content .= '<style>';
$content .= 'html{background-color:#1e2326;color:#e8e5d5;font-family:"Arial",sans-serif;font-size:0.980rem;margin:0;padding:0;}';
$content .= 'body{max-width:700px;line-height:150%;padding:20px 40px;}';
$content .= 'a{color:#d3c6aa;text-decoration:underline;}';
$content .= 'p{hyphens:auto;line-height:1.5rem;margin:0;padding:10px 0;text-align:left;word-wrap:break-word;-moz-hyphens:auto;-webkit-hyphens:auto;-o-hyphens:auto;}';
$content .= 'h1{font-size:190%;font-weight:700;line-height:160%;margin:0 0 5px 0;padding:0;}';
$content .= 'code{font-family:"Victor Mono";font-size:90%;line-height:100%;}';
$content .= '.color-red{color:#e67e80;}';
$content .= '</style>';
$content .= '</head>';
$content .= '<body'.($error == false ? '' : ' class="color-red"').'>';
$content .= $string;
$content .= '</body>';
$content .= '</html>';
return $content;
}
?>

44
functions/sql.php Executable file
View file

@ -0,0 +1,44 @@
<?php
function sql($query, $array, $method = '') {
global $sql;
try {
$prepare = $sql->prepare($query);
if($method == 'count') {
$prepare->execute($array);
$data = $prepare->fetchColumn();
return $data;
} elseif($method == 'fetch') {
$prepare->execute($array);
$data = $prepare->fetch(PDO::FETCH_ASSOC);
return $data;
} elseif($method == 'insert') {
foreach($array AS $data => $value) {
$prepare->bindValue(':'.$data, $value);
}
$prepare->execute();
return $value;
} else {
$prepare->execute($array);
return $prepare;
}
} catch(Exception $e) {
throw($e);
}
}
?>

11
functions/svg-icon.php Executable file
View file

@ -0,0 +1,11 @@
<?php
function svgicon($string) {
$arr = [
'' => ''
];
return $arr[$string];
}
?>

12
functions/url.php Executable file
View file

@ -0,0 +1,12 @@
<?php
function url($string) {
global $protocol, $host, $uri, $is_local, $config_folder;
$url_parsed = parse_url($protocol.'://'.$host . $uri);
$url_exploded = explode('/', $url_parsed['path']);
return (empty($config_folder) ? '/' : '/'.$config_folder.'/') . $string . (isset($_GET['lang']) ? '?lang='.safetag($_GET['lang']) : null);
}
?>

35
functions/validate.php Executable file
View file

@ -0,0 +1,35 @@
<?php
use Particle\Validator\Validator;
function validate($require, $string, $type) {
$v = new Validator;
if($type == 'alpha') {
$v->required($require)->alpha();
} elseif($type == 'lengthbetween-u') {
$v->required($require)->lengthBetween(5, 25);
} elseif($type == 'lengthbetween-p') {
$v->required($require)->lengthBetween(8, null);
} elseif($type == 'lengthbetween-t') {
$v->required($require)->lengthBetween(4, 100);
} elseif($type == 'lengthbetween-n') {
$v->required($require)->lengthBetween(2, 20);
} elseif($type == 'lengthbetween-s') {
$v->required($require)->lengthBetween(3, 100);
} elseif($type == 'length-p') {
$v->required($require)->length(10);
} elseif($type == 'email') {
$v->required($require)->email();
} elseif($type == 'digits') {
$v->required($require)->digits();
} elseif($type == 'regex-name') {
$v->required($require)->regex("/^[A-zåäöÅÄÖ \,\.\é\'\-]+$/i");
} elseif($type == 'regex-password') {
$v->required($require)->regex("/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\!\@\#\$\%\^\&\*]).{8,}$/");
}
return $v->validate([$require => $string])->isValid();
}
?>

23
index.php Executable file
View file

@ -0,0 +1,23 @@
<?php
require_once 'site-header.php';
echo '<section id="">';
echo '';
echo '</section>';
require_once 'site-footer.php';
?>

2
js/jquery.min.js vendored Executable file

File diff suppressed because one or more lines are too long

97
js/main.js Executable file
View file

@ -0,0 +1,97 @@
url = window.location.href;
folder_name = $('body').data('folder');
debugging = ($('body').data('debugging') == 'n' ? false : true);
$(document).ready(function () {
var current_time = new Date();
year = current_time.getFullYear();
month = ((current_time.getMonth() + 1) < 10 ? '0' : '') + (current_time.getMonth() + 1);
day = (current_time.getDate() < 10 ? '0' : '') + current_time.getDate();
});
function open_newtab(n) { var o = window.open(n, "_blank"); o.focus() }
function format_number(digits,decimal=0){return $.number(digits,decimal,',',' ')}
function select_firstfield() { $("input").each(function () { if ("" === this.value) return this.select(), !1 }) }
function msg(string, type, class_el) {
var arr_types = {
'error': {
'icon': svgicon('msg-warning'),
'color': 'red'
},
'info': {
'icon': svgicon('msg-information'),
'color': 'blue'
},
'wait': {
'icon': svgicon('msg-waiting'),
'color': 'blue'
},
'done': {
'icon': svgicon('msg-done'),
'color': 'green'
}
};
if($('.msg > div').length == 0) {
d = document.createElement('div');
$(d).appendTo('.msg');
}
$('.msg').show();
$('.msg' + (class_el == null ? '' : '.' + class_el) + ' > div').html(arr_types[type]['icon'] + string).removeClass('color-blue').removeClass('color-red').removeClass('color-green').addClass('color-' + arr_types[type]['color']);
$('input').blur();
$('html,body').animate({
scrollTop: ($((class_el == null ? '.msg' : '.msg.' + class_el)).offset().top - (is_portable == true ? (70 + 10) : 15))
}, 50);
if(type == 'wait') {
cursor('wait');
} else {
cursor('default');
}
}
function svgicon($string) {
arr = {
'msg-warning': '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-exclamation-mark" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 19v.01"></path><path d="M12 15v-10"></path></svg>',
'msg-done': '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.25" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 12l5 5l10 -10"></path></svg>',
'msg-information': '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-info-circle-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 9h-1l-.117 .007a1 1 0 0 0 0 1.986l.117 .007v3l.007 .117a1 1 0 0 0 .876 .876l.117 .007h1l.117 -.007a1 1 0 0 0 .876 -.876l.007 -.117l-.007 -.117a1 1 0 0 0 -.764 -.857l-.112 -.02l-.117 -.006v-3l-.007 -.117a1 1 0 0 0 -.876 -.876l-.117 -.007zm.01 -3l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007z" stroke-width="0" fill="currentColor"></path></svg>',
'msg-waiting': '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-loader-2" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.25" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 3a9 9 0 1 0 9 9"></path></svg>',
};
return arr[$string];
}
function cursor(type) {
if(type == 'wait') {
$('html,body').css({ 'cursor': 'wait' });
} else if(type == 'default') {
$('html,body').css({ 'cursor': 'auto' });
}
}

11
languages/gb.php Executable file
View file

@ -0,0 +1,11 @@
<?php
$lang = [
'metadata' => [
'language' => 'en',
'locale' => 'en_GB',
'description' => ''
]
];
?>

11
languages/se.php Executable file
View file

@ -0,0 +1,11 @@
<?php
$lang = [
'metadata' => [
'language' => 'se',
'locale' => 'sv_SE',
'description' => ''
]
];
?>

23
page-errors.php Normal file
View file

@ -0,0 +1,23 @@
<?php
require_once 'site-header.php';
echo '<section id="">';
echo '';
echo '</section>';
require_once 'site-footer.php';
?>

31
site-config.php Executable file
View file

@ -0,0 +1,31 @@
<?php
$site_title = 'airikr.me';
$site_protocol = 'https';
$site_domain = 'airikr.me';
$site_subdomain = null;
$site_url = $site_protocol.'://'.(empty($site_subdomain) ? null : $site_subdomain.'.') . $site_domain;
$site_url_current = sprintf(
'%s://%s/%s',
isset($_SERVER['HTTPS']) ? 'https' : 'http',
$_SERVER['HTTP_HOST'],
trim($_SERVER['REQUEST_URI'], '/\\')
);
$site_favicon = 'data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=';
$metadata_image = null;
$minified = false;
$debugging = true;
$config_folder = 'template';
$config_root = '/'.(($_SERVER['HTTP_HOST'] == 'localhost' OR strpos($_SERVER['HTTP_HOST'], '192.168') !== false) ? 'srv/http' : 'var/www');
$config_email_noreply = 'no-reply@'.$site_domain;
$config_encoding = 'ISO-8859-1';
$config_timezone = 'Europe/Stockholm';
$database_host = null;
$database_name = null;
$database_user = null;
$database_pass = null;
?>

17
site-footer.php Executable file
View file

@ -0,0 +1,17 @@
<?php
echo '</main>';
echo '</section>';
echo '</body>';
echo '</html>';
#echo '<script type="text/javascript" src="'.url('js/jquery.min.js').'"></script>';
#echo '<script type="text/javascript" src="'.url('js/main'.($minified == true ? '.min.js' : '.js?'.time()), true).'"></script>';
#echo (!file_exists('js/pages/'.str_replace('.php', '', $filename).'.js') ? null : '<script type="text/javascript" src="'.url('js/pages'.($minified == true ? '/minified' : '').'/'.str_replace('.php', '', $filename) . ($minified == true ? '.min.js' : '.js?'.time()), true).'"></script>');
?>

21
site-functions.php Executable file
View file

@ -0,0 +1,21 @@
<?php
require_once 'site-settings.php';
require_once $dir_functions.'/age.php';
require_once $dir_functions.'/checkbox.php';
require_once $dir_functions.'/create-folder.php';
require_once $dir_functions.'/date.php';
require_once $dir_functions.'/endecrypt.php';
require_once $dir_functions.'/external-link.php';
require_once $dir_functions.'/format-number.php';
require_once $dir_functions.'/pw-random.php';
require_once $dir_functions.'/safe-tag.php';
require_once $dir_functions.'/send-email.php';
require_once $dir_functions.'/simple-page.php';
require_once $dir_functions.'/sql.php';
require_once $dir_functions.'/svg-icon.php';
require_once $dir_functions.'/url.php';
require_once $dir_functions.'/validate.php';
?>

68
site-header.php Executable file
View file

@ -0,0 +1,68 @@
<?php
require_once 'site-settings.php';
echo '<!DOCTYPE html>';
echo '<html lang="sv">';
echo '<head>';
echo '<title>';
echo (empty($site_title) ? 'Template' : $site_title);
echo '</title>';
echo '<meta charset="UTF-8">';
echo '<meta name="theme-color" content="#272e33">';
echo '<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, maximum-scale=3">';
echo (count($robots) == 0 ? null : '<meta name="robots" content="'.implode(',', $robots).'">');
echo (count($google) == 0 ? null : '<meta name="robots" content="'.implode(',', $google).'">');
echo '<meta name="description" content="">';
echo '<meta http-equiv="cache-control" content="cache">';
echo '<meta http-equiv="expires" content="'.(60*60*24).'">';
echo '<meta property="og:locale" content="">';
echo '<meta property="og:locale:alternative" content="">';
echo '<meta property="og:title" content="'.$site_title.'">';
echo '<meta property="og:site_name" content="'.$site_title.'">';
echo '<meta property="og:type" content="website">';
echo '<meta property="og:url" content="'.$site_url_current.'">';
echo '<meta property="og:description" content="">';
if(!empty($metadata_image)) {
echo '<meta property="og:image" content="'.$metadata_image.'">';
echo '<meta property="og:image:secure_url" content="'.$metadata_image.'">';
echo '<meta property="og:image:height" content="'.($filename == null ? '512' : '256').'">';
echo '<meta property="og:image:width" content="'.($filename == null ? '512' : '256').'">';
echo '<meta property="og:image:type" content="image/jpeg">';
}
echo '<meta property="twitter:card" content="summary_large_image"></meta>';
echo '<meta property="twitter:url" content="'.$site_url_current.'">';
echo '<meta property="twitter:title" content="'.$site_title.'">';
echo '<meta property="twitter:description" content="">';
echo (empty($metadata_image) ? null : '<meta property="twitter:image" content="'.$metadata_image.'">');
echo '<link rel="canonical" href="'.$site_url_current.'">';
echo '<link href="'.$site_url.'" rel="me">';
echo (file_exists('manifest.json') ? '<link rel="manifest" href="'.url('manifest.json').'" crossorigin="use-credentials">' : null);
echo '<link type="image/x-icon" rel="icon" href="'.$site_favicon.'">';
echo (empty($site_url_cdn) ? null : '<link rel="dns-prefetch" href="'.$site_url_cdn.'" crossorigin="">');
echo '<link type="text/css" rel="stylesheet preload" as="style" href="'.url('css/desktop'.($minified == true ? '.min.css' : '.css?'.time())).'">';
echo (!file_exists('css/pages/'.str_replace('.php', '', $filename).'.css') ? null : '<link type="text/css" rel="stylesheet preload" as="style" href="'.url('css/pages'.($minified == true ? '/minified' : '').'/'.str_replace('.php', '', $filename) . ($minified == true ? '.min.css' : '.css?'.time())).'">');
echo '<link type="text/css" rel="stylesheet preload" as="style" href="'.url('css/portable'.($minified == true ? '.min.css' : '.css?'.time())).'">';
echo '</head>';
echo '<body';
echo ' data-folder="'.(empty($config_folder) ? '/' : '/'.$config_folder.'/').'"';
echo ' data-debugging="'.($debugging == false ? 'n' : 'y').'"';
echo '>';
echo '<section id="website">';
echo '<main>';
?>

47
site-settings.php Executable file
View file

@ -0,0 +1,47 @@
<?php session_start();
require_once 'site-config.php';
ini_set('display_errors', ($debugging == false ? 0 : 1));
ini_set('display_startup_errors', ($debugging == false ? 0 : 1));
error_reporting(E_ALL);
date_default_timezone_set($config_timezone);
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
$is_local = (($host == 'localhost' OR strpos($host, '192.168') !== false) ? true : false);
$filename = basename($_SERVER['PHP_SELF']);
$filename_get = (!empty($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : null);
$google = ['notranslate','nositelinkssearchb'];
$robots = ['nofollow','nosnippet','noarchive','noimageindex'];
$dir_files = $config_root.'/files/template';
$dir_functions = 'functions';
$dir_images = 'images';
$dir_languages = 'languages';
if(file_exists('vendor(autoload.php')) {
require_once 'vendor/autoload.php';
$Parsedown = new Parsedown();
}
require_once 'site-functions.php';
if(!empty($database_host) AND !empty($database_name) AND !empty($database_user) AND !empty($database_pass)) {
try {
$sql = new PDO('mysql:host='.$database_host.';dbname='.$database_name, $database_user, $database_pass);
$sql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo $e;
exit;
}
}
?>