Compare commits

...

37 commits
v1.3 ... master

Author SHA1 Message Date
Miroslav Šedivý
afa89836d2 increase version. 2023-01-24 18:18:53 +01:00
Miroslav Šedivý
d25b53ab33 datepicker add year increase / decrease, #44. 2023-01-24 18:18:36 +01:00
Miroslav Šedivý
f17219d054 add #sort=reverse, #44. 2023-01-24 18:02:48 +01:00
Miroslav Šedivý
1583120679 multiarch builds. 2023-01-12 22:21:09 +01:00
Miroslav Šedivý
5651c47b1d fix url escape. 2022-01-15 20:07:35 +01:00
Miroslav Šedivý
6f5e59f140 check image create errors. 2022-01-06 17:23:43 +01:00
Miroslav Šedivý
5e1a72f22e HTML escape config vars. 2022-01-06 16:36:47 +01:00
Miroslav Šedivý
08cd9e7cf8 bug fix. 2022-01-06 15:10:50 +01:00
Vincent Stans
2ad4e86ec8
Create nl.ini (#36)
Dutch Translation
2021-12-16 15:07:02 +01:00
Miroslav Šedivý
911b0be5ac fixes #35. 2021-11-20 19:36:00 +01:00
vkhurana
7d834a6d03
add config options for footer (#34) 2021-11-17 09:54:47 +01:00
Lucien Cartier-Tilet
902066ed81
Fix typos in French translation (#33) 2021-11-10 23:12:42 +01:00
Miroslav Šedivý
75788116ec Revert "add funding."
This reverts commit 57153f383c.
2021-11-10 23:04:13 +01:00
Miroslav Šedivý
2ff91c0908 bump minor version. 2021-11-06 00:10:22 +01:00
Miroslav Šedivý
57153f383c add funding. 2021-11-06 00:10:00 +01:00
Miroslav Šedivý
45955a4730 fix canocat for postgres, #32. 2021-11-01 17:06:51 +01:00
Miroslav Šedivý
1a72664f73
Merge pull request #31 from m1k1o/postgres
Add postgres support
2021-10-29 23:33:55 +02:00
Miroslav Šedivý
7231835bf5 bump version. 2021-10-29 23:28:12 +02:00
Miroslav Šedivý
d13d6ab98e update readme. 2021-10-29 23:26:44 +02:00
Miroslav Šedivý
b41c4a57fc revert debug in config. 2021-10-29 23:21:43 +02:00
Miroslav Šedivý
845b9f724a fix postgres timezone. 2021-10-29 23:13:52 +02:00
Miroslav Šedivý
f0dbd5e426 set postgres datetime. 2021-10-29 22:58:54 +02:00
Miroslav Šedivý
3652faf8ab add postgres support. 2021-10-29 21:56:50 +02:00
Miroslav Šedivý
8ad8b5ca6f add postgres schema. 2021-10-29 21:47:31 +02:00
Miroslav Šedivý
3dee0f4028 add 🇷🇺 to readme. 2021-10-29 20:44:58 +02:00
Miroslav Šedivý
8073f2ce44
Merge pull request #30 from ozzyst/f/add_ru_lang
Add support of Russian language
2021-10-28 15:33:21 +02:00
Stanislav Losev
0396958944 Add support of Russian language 2021-10-28 16:13:05 +03:00
Miroslav Šedivý
dabfd02776 dockerfile remove deprecated maintainer. 2021-08-09 17:59:08 +02:00
Miroslav Šedivý
59858cabfe do not use root mysql account. 2021-08-09 17:57:20 +02:00
Miroslav Šedivý
477912bdbf add exif, fixes #20. 2021-08-09 17:53:58 +02:00
Miroslav Šedivý
9f5393fac5 theme01 remove textarea border. 2021-07-23 15:51:01 +02:00
Miroslav Šedivý
1ae667ed5e add link to github repo. 2021-07-23 15:49:40 +02:00
Miroslav Šedivý
763bca162a remove unused code. 2021-07-23 15:40:43 +02:00
Miroslav Šedivý
b43ca9a94e use github actions. 2021-06-13 14:44:59 +02:00
Miroslav Šedivý
386707c104 fix CONCAT() for SQLite #24. 2021-06-13 12:45:52 +02:00
Miroslav Šedivý
86b3840278
Merge pull request #22 from Nixo-77/master
Implode bug fix
2021-02-21 19:07:40 +01:00
Nixo-77
d5ecdf330c
Implode bug fix 2021-02-21 19:03:33 +01:00
19 changed files with 476 additions and 103 deletions

1
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1 @@
github: [ m1k1o ]

58
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,58 @@
name: "CI for builds"
on:
push:
branches:
- master
tags:
- 'v*'
env:
IMAGE_NAME: m1k1o/blog
jobs:
build:
runs-on: ubuntu-latest
#
# do not run on forks
#
if: github.repository_owner == 'm1k1o'
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
-
name: Available platforms
run: echo ${{ steps.buildx.outputs.platforms }}
-
name: Extract metadata (tags, labels) for Docker
uses: docker/metadata-action@v3
id: meta
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
-
name: Log in to the Container registry
uses: docker/login-action@v1
with:
username: ${{ github.actor }}
password: ${{ secrets.DOCKER_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true

View file

@ -1,9 +1,7 @@
FROM php:7.4-apache
MAINTAINER Miroslav Sedivy
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends \
apt-get install -y --no-install-recommends libpq-dev \
#
# install curl
libcurl4-openssl-dev \
@ -20,7 +18,7 @@ RUN set -eux; apt-get update; \
--with-jpeg --with-webp --with-xpm --with-freetype; \
#
# install extensions
docker-php-ext-install curl gd pdo pdo_mysql; \
docker-php-ext-install curl gd pdo pdo_mysql pdo_pgsql exif; \
#
# set up environment
a2enmod rewrite;

105
README.md
View file

@ -53,32 +53,85 @@ docker run -d \
m1k1o/blog:latest
```
Or in docker-compose format:
```yml
version: "3"
services:
blog:
image: m1k1o/blog:latest
restart: unless-stopped
environment:
TZ: Europe/Vienna
BLOG_TITLE: Blog
BLOG_NAME: Max Musermann
BLOG_NICK: username
BLOG_PASS: password
BLOG_LANG: en
ports:
- 80:80
volumes:
- ./data:/var/www/html/data
```
Or for docker-compose format, see [docker-compose.yml](docker-compose.yml).
## Install standalone app using `docker-compose` with mysql
## Install standalone app using `docker-compose` with external database
You need to install [docker-compose](https://docs.docker.com/compose/install/).
### Step 1: Download and run `docker-compose.yml`.
### MySQL
```yaml
version: "3"
services:
webserver:
image: m1k1o/blog:latest
container_name: blog_apache
environment:
TZ: Europe/Vienna
BLOG_DB_CONNECTION: mysql
BLOG_MYSQL_HOST: mariadb
BLOG_MYSQL_PORT: 3306
BLOG_MYSQL_USER: blog
BLOG_MYSQL_PASS: blog # use secure password
BLOG_DB_NAME: blog
restart: unless-stopped
ports:
- ${HTTP_PORT-80}:80
volumes:
- ${DATA-./data}:/var/www/html/data
mariadb:
image: mariadb:10.1
container_name: blog_mariadb
environment:
MYSQL_USER: blog
MYSQL_PASSWORD: blog # use secure password
MYSQL_DATABASE: blog
MYSQL_ROOT_PASSWORD: root # use secure password
restart: unless-stopped
volumes:
- mariadb:/var/lib/mysql
- ./app/db/mysql:/docker-entrypoint-initdb.d:ro
volumes:
mariadb:
```
### Postgres
```yaml
version: "3"
services:
webserver:
image: m1k1o/blog:latest
container_name: blog_apache
environment:
TZ: Europe/Vienna
BLOG_DB_CONNECTION: postgres
BLOG_POSTGRES_HOST: postgres
BLOG_POSTGRES_PORT: 5432
BLOG_POSTGRES_USER: blog
BLOG_POSTGRES_PASS: blog # use secure password
BLOG_DB_NAME: blog
restart: unless-stopped
ports:
- ${HTTP_PORT-80}:80
volumes:
- ${DATA-./data}:/var/www/html/data
postgres:
image: postgres:14
container_name: blog_postgres
environment:
POSTGRES_USER: blog
POSTGRES_PASSWORD: blog # use secure password
POSTGRES_DB: blog
restart: unless-stopped
volumes:
- postgres:/var/lib/postgresql/data
- ./app/db/postgres:/docker-entrypoint-initdb.d:ro
volumes:
postgres:
```
### Step 1: Run `docker-compose.yml`.
Select one of configurations above and save it to `docker-compose.yml`. Then run:
```sh
wget https://raw.githubusercontent.com/m1k1o/blog/master/docker-compose.yml
docker-compose up -d
```
@ -155,9 +208,10 @@ To check if your server is set up correctly, turn on a debug mode (in config add
* Upload images using CTRL + V *(paste it into textarea)*.
* Highlight code in post using `[code]..your code..[/code]`.
* Highlight your goal using `[goal]Text of your goal.[/goal]`.
* Use tags in posts (allowed characters `A-Za-z0-9-_` terminated by space or EOL): `#song`
* Sort posts by hashtags: `http://blog/#tag=songs`
* Sort posts by location in url using: `http://blog/#loc=Vienna`.
* Use tags in posts (allowed characters `A-Za-z0-9-_` terminated by space or EOL): `#song`.
* Sort posts in reverse order (oldest first): `http://blog/#sort=reverse`.
* Filter posts by hashtags: `http://blog/#tag=songs`.
* Filter posts by location in url using: `http://blog/#loc=Vienna`.
* Display posts from chosen date using (format YYYY-MM-DD or YYY-MM): `http://blog/#from=2017-06`.
* Display posts to chosen date using (format YYYY-MM-DD or YYY-MM): `http://blog/#to=2017-06`.
* Combine parameters in url using `&`, e.g. show posts between dates: `http://blog/#from=2017-06&to=2017-08`.
@ -217,3 +271,4 @@ Feel free to create new PR and add a new language. Specify language in config or
* cz - 🇨🇿 Czech (thanks @djfinch)
* bs - 🇧🇦 Bosnian (thanks @hajro92)
* es - 🇪🇸 Spanish (thanks @ManuLinares)
* ru - 🇷🇺 Russian (thanks @ozzyst)

View file

@ -24,12 +24,27 @@ class DB
return Config::get_safe('db_connection', 'sqlite');
}
// CONCAT() does not exist in SQLite, using || instead
// for postgres, ERROR: could not determine data type of parameter $1
public final static function concat(){
$values = func_get_args();
if(DB::connection() === 'sqlite' || DB::connection() === 'postgres') {
return implode(" || ", $values);
} else {
return 'CONCAT('.implode(", ", $values).')';
}
}
// Initialise PDO object
private final function __construct(){
switch(DB::connection()) {
case 'mysql':
$this->mysql_connect();
break;
case 'postgres':
$this->postgres_connect();
break;
case 'sqlite':
$this->sqlite_connect();
break;
@ -81,6 +96,48 @@ class DB
}
}
private final function postgres_connect(){
$host = Config::get_safe('postgres_host', false);
$port = Config::get_safe('postgres_port', false);
$socket = Config::get_safe('postgres_socket', false);
if($socket === false && $host === false){
throw new DBException("Postgres host or socket must be defined.");
}
// Try to connect
try {
$this->_PDO = new \PDO(
// Server
'pgsql:'.
($socket !== false
? 'unix_socket='.$socket
: 'host='.$host.($port !== false ? ';port='.$port : '')
).
// DB
';dbname='.Config::get('db_name').
// Charset
';options=\'--client_encoding=UTF8\'',
// Username
Config::get('postgres_user'),
// Password
Config::get_safe('postgres_pass', ''),
// Set attributes
[
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]
);
$this->_PDO->exec(
// Set timezone
'SET TIME ZONE "'.date('e').'";'
);
} catch (PDOException $e) {
throw new DBException($e->getMessage());
}
}
private final function sqlite_connect(){
$sqlite_db = PROJECT_PATH.Config::get_safe('sqlite_db', "data/sqlite.db");
@ -154,6 +211,11 @@ class DB
$sql = $params[0];
unset($params[0]);
// Replace backticks with " for postgres
if(DB::connection() === 'postgres') {
$sql = str_replace("`", '"', $sql);
}
// Debug mode
if(Config::get_safe('debug', false)){
echo "<!-- ".$sql." + ".json_encode($params)." -->\n";

View file

@ -0,0 +1,26 @@
CREATE TABLE images (
"id" serial PRIMARY KEY,
"name" varchar(255) NOT NULL,
"path" varchar(255) DEFAULT NULL,
"thumb" varchar(255) DEFAULT NULL,
"type" varchar(10) NOT NULL,
"md5" char(32) NOT NULL,
"datetime" timestamp NOT NULL,
"status" int NOT NULL
);
CREATE TYPE privacy_t as enum('private','friends','public');
CREATE TABLE posts (
"id" serial PRIMARY KEY,
"text" text NOT NULL,
"plain_text" text NOT NULL,
"feeling" varchar(255) NOT NULL,
"persons" varchar(255) NOT NULL,
"location" varchar(255) NOT NULL,
"content" varchar(1000) NOT NULL,
"content_type" varchar(255) NOT NULL,
"privacy" privacy_t NOT NULL,
"datetime" timestamp NOT NULL,
"status" int NOT NULL
);

View file

@ -110,15 +110,16 @@ class Image
}
$old_image = $imgcreatefrom($source_path);
if ($old_image === false) return false;
$new_image = imagecreatetruecolor($new_w, $new_h);
imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_w, $new_h, $source_w, $source_h);
$new_image = self::fix_orientation($source_path, $new_image);
$old_image = self::fix_orientation($source_path, $old_image);
$imgt($new_image, $thumb_path);
$imgt($old_image, $source_path);
return true;
return $imgt($new_image, $thumb_path)
&& $imgt($old_image, $source_path);
}
public static function upload(){

View file

@ -40,9 +40,9 @@ October = "Octobre"
November = "Novembre"
December = "Décembre"
Time: = "Heure:"
Hour: = "Heure:"
Minute: = "Minutes:"
Time: = "Heure :"
Hour: = "Heure :"
Minute: = "Minutes :"
This post will be deleted and you'll no longer be able to find it. You can also edit this post if you just want to change something. = "Cette publication sera supprimée et vous ne pourrez plus la retrouver. Vous pouvez aussi la modifier si vous souhaitez simplement changer quelque chose."
@ -57,11 +57,11 @@ Show hidden content = "Montrer le contenu caché"
Show all posts = "Montrer toutes les publications"
; user.class.php
You are already logged in. = "Vous êtes déjà connectés."
You are already logged in. = "Vous êtes déjà connecté."
The nick or password is incorrect. = "Votre pseudo ou mot de passe est incorrect."
You can't log out. There is no account. = "Vous ne pouvez pas vous déconnecter, les comptes sont désactivés."
You are not even logged in. = "Vous nêtes même pas connectés."
You are not even logged in. = "Vous nêtes pas connecté."
; post.class.php
You need to be logged in to perform this action. = "Vous devez être connectés pour pouvoir faire ça."
You need to be logged in to perform this action. = "Vous devez être connecté pour pouvoir faire ça."
No data. = "Aucune données."

67
app/lang/nl.ini Normal file
View file

@ -0,0 +1,67 @@
; index.html
Show More = "Verder Lezen"
Login = "Aanmelden"
Logout = "Afmelden"
Nick = "Gebruiker"
Password = "Wachtwoord"
Cancel = "Annuleren"
Post = "Bericht"
Edit Post = "Wijzig Bericht"
Change Date = "Wijzig Datum"
Hide from Timeline = "Verbergen van Tijdlijn"
Show on Timeline = "Laten zien op Tijdlijn"
Delete Post = "Verwijder Bericht"
Drag photos here = "Sleep foto's hier"
Drop photos here = "Gooi foto's hier"
What's on your mind? = "Waar ben je mee bezig?"
Feeling = "Gevoel"
How are you feeling? = "Hoe voel je je?"
With = "Met"
Who are you with? = "Met wie ben je?"
At = "Bij"
Where are you? = "Waar ben je?"
Save = "Opslaan"
January = "Januari"
February = "Februari"
March = "Maart"
April = "April"
May = "Mei"
June = "Juni"
July = "Juli"
August = "Augustus"
September = "September"
October = "Oktober"
November = "November"
December = "December"
Time: = "Tijd:"
Hour: = "Uur:"
Minute: = "Minuten:"
This post will be deleted and you'll no longer be able to find it. You can also edit this post if you just want to change something. = "Dit bericht word verwijderd en kan niet meer worden gevonden. Je kan ook het bericht wijzigen als je dat liever wilt."
with = "met"
here: = "Bij:"
Public = "Openbaar"
Friends = "Vrienden"
Only me = "Alleen ik"
Show hidden content = "Laat verborgen berichten zien"
Show all posts = "Alle berichten zien"
; user.class.php
You are already logged in. = "Je bent al ingelogt."
The nick or password is incorrect. = "De gebruiken of het Wachtwoord is onjuist."
You can't log out. There is no account. = "Je kan niet Afmelden. Er is geen Account."
You are not even logged in. = "Je ben niet eens ingelogt."
; post.class.php
You need to be logged in to perform this action. = "Je moet ingelogged zijn om deze actie uit te voeren."
No data. = "Geen data."

67
app/lang/ru.ini Normal file
View file

@ -0,0 +1,67 @@
; index.html
Show More = "Показать больше"
Login = "Войти"
Logout = "Выйти"
Nick = "Логин"
Password = "Пароль"
Cancel = "Отмена"
Post = "Пост"
Edit Post = "Редактировать пост"
Change Date = "Изменить дату"
Hide from Timeline = "Скрыть из ленты"
Show on Timeline = "Показать в ленте"
Delete Post = "Удалить пост"
Drag photos here = "Перетащите сюда фото"
Drop photos here = "Оставь фото здесь"
What's on your mind? = "О чем ты думаешь?"
Feeling = "Ощущения"
How are you feeling? = "Как ты себя чувствуешь?"
With = "В компании"
Who are you with? = "С кем ты?"
At = "Локация"
Where are you? = "Где ты?"
Save = "Сохранить"
January = "Январь"
February = "Февраль"
March = "Март"
April = "Апрель"
May = "Май"
June = "Июнь"
July = "Июль"
August = "Август"
September = "Сентябрь"
October = "Октябрь"
November = "Ноябрь"
December = "Декабрь"
Time: = "Время:"
Hour: = аc:"
Minute: = "Минута:"
This post will be deleted and you'll no longer be able to find it. You can also edit this post if you just want to change something. = "Этот пост будет удален, и вы больше не сможете его найти. Вы также можете отредактировать этот пост, если просто хотите что-то изменить"
with = "с"
here: = "здесь:"
Public = "Публичный"
Friends = "Друзья"
Only me = "Только я"
Show hidden content = "Показать скрытый контент"
Show all posts = "Показать все посты"
; user.class.php
You are already logged in. = "Вы уже залогинены."
The nick or password is incorrect. = "Логин или пароль неверный."
You can't log out. There is no account. = "Вы не можете выйти. Вы не залогинены."
You are not even logged in. = "Вы не авторизовались."
; post.class.php
You need to be logged in to perform this action. = "Вы должны быть залогинены, чтобы выполнить это действие."
No data. = "Нет данных."

View file

@ -204,6 +204,8 @@ class Post
if (DB::connection() === 'sqlite') {
$datetime = "strftime('%Y %m %d %H %M', `posts`.`datetime`)";
} else if (DB::connection() === 'postgres') {
$datetime = "to_char(datetime,'YYYY MM DD HH24 MI')";
} else {
$datetime = "DATE_FORMAT(`datetime`,'%Y %c %e %k %i')";
}
@ -425,10 +427,14 @@ class Post
if (DB::connection() === 'sqlite') {
$datetime = "strftime('%d %m %Y %H:%M', `posts`.`datetime`)";
} else if (DB::connection() === 'postgres') {
$datetime = "to_char(posts.datetime,'DD Mon YYYY HH24:MI')";
} else {
$datetime = "DATE_FORMAT(`posts`.`datetime`,'%d %b %Y %H:%i')";
}
$like_match = "LIKE ".DB::concat("'%'", "?", "'%'");
return DB::get_instance()->query("
SELECT
`id`, `text`, `feeling`, `persons`, `location`, `privacy`, `content_type`, `content`,
@ -439,11 +445,11 @@ class Post
($from ? "`posts`.`datetime` > ? AND " : "").
($to ? "`posts`.`datetime` < ? AND " : "").
($id ? "`id` = ? AND " : "").
($tag ? "`plain_text` LIKE CONCAT('%', ?, '%') AND " : "").
($loc ? "`location` LIKE CONCAT('%', ?, '%') AND " : "").
($person ? "`persons` LIKE CONCAT('%', ?, '%') AND " : "").
($tag ? "`plain_text` $like_match AND " : "").
($loc ? "`location` $like_match AND " : "").
($person ? "`persons` $like_match AND " : "").
"`status` <> 5
ORDER BY `posts`.`datetime` DESC
ORDER BY `posts`.`datetime` ".(@$r["sort"] == 'reverse' ? "ASC" : "DESC")."
LIMIT ? OFFSET ?
", $from, $to, $id, $tag, $loc, $person, $r["limit"], $r["offset"]
)->all();

View file

@ -17,10 +17,10 @@ if(Config::get_safe('debug', false)){
error_reporting(E_ALL);
// Check extensions
$required = ['curl', 'PDO', 'pdo_mysql', 'gd'];
$required = ['curl', 'PDO', 'pdo_mysql', 'gd', 'exif'];
$loaded = get_loaded_extensions();
if($missing = array_diff($required, $loaded)){
die("Missing extensions, please install: ".impode(", ", $missing));
die("Missing extensions, please install: ".implode(", ", $missing));
}
}

View file

@ -11,6 +11,15 @@ db_connection = sqlite
;mysql_pass = root
;db_name = blog
;[database]
;db_connection = postgres
;postgres_socket = /tmp/postgres.sock
;postgres_host = localhost
;postgres_port = 5432
;postgres_user = root
;postgres_pass = root
;db_name = blog
[profile]
title = Blog
name = Max Musermann
@ -30,6 +39,7 @@ theme = theme02
;styles[] = static/styles/custom1.css
;styles[] = static/styles/custom2.css
;scripts = static/styles/scripts.css
;footer = "Edit this if you really want to remove my backlink :("
[bbcode]
;bbtags[quote] = "<quote>{param}</quote>"
@ -62,7 +72,6 @@ logs_path = data/logs/
[system]
;timezone = Europe/Vienna
system_name = blog
version = 1.3
version = 1.42
debug = false
logs = false

View file

@ -1,31 +1,17 @@
version: "3"
services:
webserver:
blog:
image: m1k1o/blog:latest
container_name: blog_apache
environment:
TZ: Europe/Vienna
BLOG_DB_CONNECTION: mysql
BLOG_MYSQL_HOST: mariadb
BLOG_MYSQL_PORT: 3306
BLOG_MYSQL_USER: root
BLOG_MYSQL_PASS: root
BLOG_DB_NAME: blog
restart: unless-stopped
environment:
TZ: Europe/Vienna
BLOG_TITLE: Blog
BLOG_NAME: Max Musermann
BLOG_NICK: username
BLOG_PASS: password
BLOG_LANG: en
ports:
- ${HTTP_PORT-80}:80
volumes:
- ${DATA-./data}:/var/www/html/data
mariadb:
image: mariadb:10.1
container_name: blog_mariadb
environment:
MYSQL_DATABASE: blog
MYSQL_ROOT_PASSWORD: root
restart: unless-stopped
- 80:80
volumes:
- mariadb:/var/lib/mysql
- ./app/db/mysql:/docker-entrypoint-initdb.d:ro
volumes:
mariadb:
- ./data:/var/www/html/data

View file

@ -10,6 +10,10 @@ if(empty($_SESSION['token'])){
}
}
function escape($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
//$.ajaxSetup({headers:{'Csrf-Token':'token'}});
Log::put("visitors");
@ -40,6 +44,7 @@ if(!empty($styles)){
}
$styles = array_unique($styles);
$styles = array_map('escape', $styles);
$styles_html = '<link href="'.implode('" rel="stylesheet" type="text/css"/>'.PHP_EOL.'<link href="', $styles).'" rel="stylesheet" type="text/css"/>'.PHP_EOL;
}
@ -47,32 +52,39 @@ if(!empty($styles)){
$scripts = Config::get_safe("scripts", []);
$scripts_html = '';
if(!empty($scripts)){
if(!is_array($styles)){
$styles = [$styles];
if(!is_array($scripts)){
$scripts = [$scripts];
}
$scripts = array_unique($scripts);
$scripts = array_map('escape', $scripts);
$scripts_html = '<script src="'.implode('" type="text/javascript"></script>'.PHP_EOL.'<script src="', $scripts).'" type="text/javascript"></script>'.PHP_EOL;
}
// Use version suffix in URLs to prevent cache
$versionSuffix = '';
if (Config::get_safe("version", false)) {
$versionSuffix = '?v='.rawurlencode(Config::get("version"));
}
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><?php echo Config::get("title"); ?></title>
<title><?php echo escape(Config::get("title")); ?></title>
<meta name="robots" content="noindex, nofollow">
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<link href="static/styles/main.css?v=<?php echo Config::get("version"); ?>" rel="stylesheet" type="text/css" />
<link href="static/styles/<?php echo Config::get_safe("theme", "theme01"); ?>.css?v=<?php echo Config::get("version"); ?>" rel="stylesheet" type="text/css" />
<link href="static/styles/main.css<?php echo $versionSuffix?>" rel="stylesheet" type="text/css" />
<link href="static/styles/<?php echo rawurlencode(Config::get_safe("theme", "theme01")); ?>.css<?php echo $versionSuffix?>" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans&amp;subset=all" rel="stylesheet">
<link href="static/styles/lightbox.css" rel="stylesheet" type="text/css" />
<?php echo Config::get("highlight") ? '<link href="static/styles/highlight-monokai-sublime.css" rel="stylesheet" type="text/css" />' : ''; ?>
<?php echo Config::get_safe("highlight", false) ? '<link href="static/styles/highlight-monokai-sublime.css" rel="stylesheet" type="text/css" />'.PHP_EOL : ''; ?>
<?php echo $styles_html; ?>
</head>
@ -103,7 +115,6 @@ if(!empty($scripts)){
</div>
<div class="modal-footer">
<div class="buttons">
<!--<div class="left"><a>Register</a> - <a>Forgot Password</a></div>-->
<a class="button gray close"><?php echo __("Cancel"); ?></a>
<button type="button" class="button blue do_login"><?php echo __("Login"); ?></button>
</div>
@ -170,7 +181,7 @@ if(!empty($scripts)){
<div class="modal-body drop_space">
<div class="e_drag"><span><?php echo __("Drag photos here"); ?></span></div>
<div class="e_drop"><span><?php echo __("Drop photos here"); ?></span></div>
<img src="<?php echo Config::get("pic_small"); ?>" width="40" height="40" class="e_profile">
<img src="<?php echo escape(Config::get("pic_small")); ?>" width="40" height="40" class="e_profile">
<!--<div class="e_text" contenteditable="true"></div>-->
<div class="t_area">
<textarea class="e_text" placeholder="<?php echo __("What's on your mind?"); ?>"></textarea>
@ -282,10 +293,10 @@ if(!empty($scripts)){
<a class="button"><?php echo __("Show hidden content"); ?></a>
</div>
<div class="b_header">
<img src="<?php echo Config::get("pic_small"); ?>" width="40" height="40" class="b_profile">
<img src="<?php echo escape(Config::get("pic_small")); ?>" width="40" height="40" class="b_profile">
<div class="b_desc">
<div class="b_sharer">
<span class="b_name"><?php echo Config::get("name"); ?></span><span class="b_options"> - </span><span class="b_feeling"></span><span class="b_with"> <?php echo __("with"); ?> </span><span class="b_persons"></span><span class="b_here"> <?php echo __("here:"); ?> </span><span class="b_location"></span>
<span class="b_name"><?php echo escape(Config::get("name")); ?></span><span class="b_options"> - </span><span class="b_feeling"></span><span class="b_with"> <?php echo __("with"); ?> </span><span class="b_persons"></span><span class="b_here"> <?php echo __("here:"); ?> </span><span class="b_location"></span>
</div>
<i class="privacy_icon"></i>
<a class="b_date"></a>
@ -305,18 +316,18 @@ if(!empty($scripts)){
</div>
<div class="bluebar">
<h1><?php echo Config::get("title"); ?></h1>
<h1><?php echo escape(Config::get("title")); ?></h1>
</div>
<div class="headbar">
<div class="cover">
<?php echo $header; ?>
<div class="overlay"></div>
<?php echo (Config::get_safe("cover", false) ? '<img src="'.Config::get("cover").'">' : (empty($header) ? '<div style="padding-bottom: 37%;"></div>' : '')); ?>
<?php echo (Config::get_safe("cover", false) ? '<img src="'.escape(Config::get("cover")).'">' : (empty($header) ? '<div style="padding-bottom: 37%;"></div>' : '')); ?>
<div class="profile">
<img src="<?php echo Config::get("pic_big"); ?>">
<img src="<?php echo escape(Config::get("pic_big")); ?>">
</div>
<div class="name"><?php echo Config::get("name"); ?></div>
<div class="name"><?php echo escape(Config::get("name")); ?></div>
</div>
<div id="headline"></div>
</div>
@ -330,16 +341,18 @@ if(!empty($scripts)){
<div id="eof_feed">
<img src="static/images/zpEYXu5Wdu6.png">
<p><?php echo Config::get("version"); ?> &copy; 2016-2020 <br>Miroslav Šedivý</p>
<p><?php echo escape(Config::get("version")); ?> &copy; 2016-2022<br>
<?php echo Config::get_safe("footer", false) ? escape(Config::get_safe("footer")) : '<a href="https://github.com/m1k1o/blog" class="link" title="m1k1o/blog github repository" target="_blank">m1k1o/blog</a>'; ?>
</p>
</div>
<script src="static/scripts/jquery.min.js"></script>
<script>$["\x61\x6A\x61\x78\x53\x65\x74\x75\x70"]({"\x68\x65\x61\x64\x65\x72\x73":{"\x43\x73\x72\x66-\x54\x6F\x6B\x65\x6E":"<?php echo $_SESSION['token'];?>"}});</script>
<script src="static/scripts/lightbox.js"></script>
<script src="static/scripts/datepick.js?v=<?php echo Config::get("version"); ?>"></script>
<script src="static/scripts/datepick.js<?php echo $versionSuffix?>"></script>
<script src="static/scripts/autosize.js"></script>
<?php echo Config::get("highlight") ? '<script src="static/scripts/highlight-10.1.2.min.js"></script><script>hljs.initHighlightingOnLoad();</script>' : ''; ?>
<script src="static/scripts/app.js?v=<?php echo Config::get("version"); ?>"></script>
<?php echo Config::get_safe("highlight", false) ? '<script src="static/scripts/highlight-10.1.2.min.js"></script><script>hljs.initHighlightingOnLoad();</script>'.PHP_EOL : ''; ?>
<script src="static/scripts/app.js<?php echo $versionSuffix?>"></script>
<?php echo $scripts_html; ?>
</body>

View file

@ -13,6 +13,7 @@ var posts = {
limit: 5, // Limit posts per load
offset: 0, // Current offset
sort: "default", // Default is from newest to oldest posts (use reverse for oldest to newest)
filter: {
from: null, // Show posts from specified date
@ -34,6 +35,10 @@ var posts = {
// Update ID hash
location.hash.replace(/([a-z]+)\=([^\&]+)/g, function(_, key, value){
if (key == "sort") {
posts.sort = decodeURIComponent(value);
return;
}
posts.filter[key] = decodeURIComponent(value);
$(".more_posts").show();
});
@ -72,6 +77,7 @@ var posts = {
action: "load",
limit: posts.limit,
offset: posts.offset,
sort: posts.sort,
filter: posts.filter
},
success: function(posts_data){

View file

@ -51,9 +51,11 @@ var datepick = function(container) {
var thead = $(
'<thead>' +
'<tr>' +
'<th><button type="button" class="button blue prev_y" title="Previous Year">&lt;&lt;</button></th>' +
'<th><button type="button" class="button blue prev" title="Previous Month">&lt;</button></th>' +
'<th class="month-pick" colspan="5" title="Select Month">'+this.months[this.m]+' '+this.y+'</th>' +
'<th class="month-pick" colspan="3" title="Select Month">'+this.months[this.m]+' '+this.y+'</th>' +
'<th><button type="button" class="button blue next" title="Next Month">&gt;</button></th>' +
'<th><button type="button" class="button blue next_y" title="Next Year">&gt;&gt;</button></th>' +
'</tr>' +
'<tr>' +
'<th>Mo</th>' +
@ -68,12 +70,22 @@ var datepick = function(container) {
);
var x = this;
$(thead).find(".prev_y").click(function(){
x.dec_y();
x.load_table();
$(thead).find(".month-pick").text(x.months[x.m]+' '+x.y);
});
$(thead).find(".prev").click(function(){
x.dec_m();
x.load_table();
$(thead).find(".month-pick").text(x.months[x.m]+' '+x.y);
});
$(thead).find(".next_y").click(function(){
x.inc_y();
x.load_table();
$(thead).find(".month-pick").text(x.months[x.m]+' '+x.y);
});
$(thead).find(".next").click(function(){
x.inc_m();
x.load_table();

View file

@ -114,6 +114,10 @@ body {
text-transform: uppercase;
}
#eof_feed .link {
color: #90949c;
}
.show_more {
height: 40px;
line-height: 40px;
@ -126,7 +130,6 @@ body {
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 75%,rgba(255,255,255,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#ffffff',GradientType=0 );
cursor: pointer;
vertical-align: bottom;
}
.b_post {
@ -587,11 +590,6 @@ body {
margin: 8px;
}
.modal-footer .buttons .left {
display: inline-block;
float: left;
}
.modal-footer:before,
.modal-footer:after {
content: " ";
@ -779,6 +777,8 @@ body {
min-height: 88px;
max-width: 100%;
min-width: 100%;
background: transparent;
border: 0;
}
.options {
@ -1055,7 +1055,8 @@ code {
text-align: center;
}
.datepicker table {
display: inline-block;
width: 100%;
margin: 5px 0;
}
.datepicker th,
@ -1063,6 +1064,9 @@ code {
width: 12.5%;
}
.datepicker th {
padding: 5px 0;
}
.datepicker td {
color: #999;
padding: 5px;

View file

@ -181,6 +181,10 @@ body {
text-transform: uppercase;
}
#eof_feed .link {
color: var(--secondary-text);
}
.show_more {
height: 40px;
line-height: 40px;
@ -192,7 +196,6 @@ body {
background: -webkit-linear-gradient(top, transparent 0%,var(--primary-background) 75%,var(--primary-background) 100%);
background: linear-gradient(to bottom, transparent 0%,var(--primary-background) 75%,var(--primary-background) 100%);
cursor: pointer;
vertical-align: bottom;
}
.b_post {
@ -714,11 +717,6 @@ body {
margin-right: 0;
}
.modal-footer .buttons .left {
display: inline-block;
float: left;
}
.modal-footer:before,
.modal-footer:after {
content: " ";
@ -1175,7 +1173,8 @@ code {
text-align: center;
}
.datepicker table {
display: inline-block;
width: 100%;
margin: 5px 0;
}
.datepicker th,
@ -1183,6 +1182,9 @@ code {
width: 12.5%;
}
.datepicker th {
padding: 5px 0;
}
.datepicker td {
color: var(--datepicker-inactive-month);
padding: 5px;