mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-12 01:50:48 +01:00
commit
19fa804116
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
||||
**/.git
|
||||
**/.gitignore
|
||||
/local-instances
|
||||
**/.gitkeep
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -44,5 +44,6 @@ Thumbs.db
|
||||
#vichan custom
|
||||
favicon.ico
|
||||
/static/spoiler.png
|
||||
/local-instances
|
||||
|
||||
/vendor/
|
||||
|
@ -119,6 +119,11 @@ WebM support
|
||||
------------
|
||||
Read `inc/lib/webm/README.md` for information about enabling webm.
|
||||
|
||||
Docker
|
||||
------------
|
||||
Vichan comes with a Dockerfile and docker-compose configuration, the latter aimed primarily at development and testing.
|
||||
See the `docker/doc.md` file for more information.
|
||||
|
||||
vichan API
|
||||
----------
|
||||
vichan provides by default a 4chan-compatible JSON API. For documentation on this, see:
|
||||
|
40
docker-compose.yml
Normal file
40
docker-compose.yml
Normal file
@ -0,0 +1,40 @@
|
||||
services:
|
||||
#nginx webserver + php 8.x
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/nginx/Dockerfile
|
||||
ports:
|
||||
- "9090:80"
|
||||
depends_on:
|
||||
- db
|
||||
volumes:
|
||||
- ./local-instances/1/www:/var/www/html
|
||||
- ./docker/nginx/vichan.conf:/etc/nginx/conf.d/default.conf
|
||||
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./docker/nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf
|
||||
links:
|
||||
- php
|
||||
|
||||
php:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/php/Dockerfile
|
||||
volumes:
|
||||
- ./local-instances/1/www:/var/www
|
||||
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
|
||||
- ./docker/php/jit.ini:/usr/local/etc/php/conf.d/jit.ini
|
||||
|
||||
#MySQL Service
|
||||
db:
|
||||
image: mysql:8.0.35
|
||||
container_name: db
|
||||
restart: unless-stopped
|
||||
tty: true
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
MYSQL_DATABASE: vichan
|
||||
MYSQL_ROOT_PASSWORD: password
|
||||
volumes:
|
||||
- ./local-instances/1/mysql:/var/lib/mysql
|
16
docker/doc.md
Normal file
16
docker/doc.md
Normal file
@ -0,0 +1,16 @@
|
||||
The `php-fpm` process runs containerized.
|
||||
The php application always uses `/var/www` as it's work directory and home folder, and if `/var/www` is bind mounted it
|
||||
is necessary to adjust the path passed via FastCGI to `php-fpm` by changing the root directory to `/var/www`.
|
||||
This can achieved in nginx by setting the `fastcgi_param SCRIPT_FILENAME` to `/var/www/$fastcgi_script_name;`
|
||||
|
||||
The default docker compose settings are intended for development and testing purposes.
|
||||
The folder structure expected by compose is as follows
|
||||
|
||||
```
|
||||
<vichan-project>
|
||||
└── local-instances
|
||||
└── 1
|
||||
├── mysql
|
||||
└── www
|
||||
```
|
||||
The vichan container is by itself much less rigid.
|
8
docker/nginx/Dockerfile
Normal file
8
docker/nginx/Dockerfile
Normal file
@ -0,0 +1,8 @@
|
||||
FROM nginx:1.25.3-alpine
|
||||
|
||||
COPY . /code
|
||||
RUN adduser --system www-data \
|
||||
&& adduser www-data www-data
|
||||
|
||||
CMD [ "nginx", "-g", "daemon off;" ]
|
||||
EXPOSE 80
|
34
docker/nginx/nginx.conf
Normal file
34
docker/nginx/nginx.conf
Normal file
@ -0,0 +1,34 @@
|
||||
# This and proxy.conf are based on
|
||||
# https://github.com/dead-guru/devichan/blob/master/nginx/nginx.conf
|
||||
|
||||
user www-data;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /dev/stdout warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Switch logging to console out to view via Docker
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stdout warn;
|
||||
sendfile on;
|
||||
keepalive_timeout 5;
|
||||
|
||||
gzip on;
|
||||
gzip_http_version 1.0;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/xml text/plain text/css application/xhtml+xml application/xml application/rss+xml application/atom_xml application/x-javascript application/x-httpd-php;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-available/*.conf;
|
||||
}
|
40
docker/nginx/proxy.conf
Normal file
40
docker/nginx/proxy.conf
Normal file
@ -0,0 +1,40 @@
|
||||
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=czone:4m max_size=50m inactive=120m;
|
||||
proxy_temp_path /var/tmp/nginx;
|
||||
proxy_cache_key "$scheme://$host$request_uri";
|
||||
|
||||
|
||||
map $http_forwarded_request_id $x_request_id {
|
||||
"" $request_id;
|
||||
default $http_forwarded_request_id;
|
||||
}
|
||||
|
||||
map $http_forwarded_forwarded_host $forwardedhost {
|
||||
"" $host;
|
||||
default $http_forwarded_forwarded_host;
|
||||
}
|
||||
|
||||
|
||||
map $http_x_forwarded_proto $fcgi_https {
|
||||
default "";
|
||||
https on;
|
||||
}
|
||||
|
||||
map $http_x_forwarded_proto $real_scheme {
|
||||
default $scheme;
|
||||
https https;
|
||||
}
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Server $host;
|
||||
|
||||
real_ip_header X-Forwarded-For;
|
||||
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 172.18.0.0;
|
||||
set_real_ip_from 192.168.0.0/24;
|
||||
set_real_ip_from 127.0.0.0/8;
|
||||
|
||||
real_ip_recursive on;
|
66
docker/nginx/vichan.conf
Normal file
66
docker/nginx/vichan.conf
Normal file
@ -0,0 +1,66 @@
|
||||
upstream php-upstream {
|
||||
server php:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
server_name vichan;
|
||||
root /var/www/html;
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
|
||||
index index.html index.php;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
location ~ ^([^.\?]*[^\/])$ {
|
||||
try_files $uri @addslash;
|
||||
}
|
||||
|
||||
# Expire rules for static content
|
||||
# Media: images, icons, video, audio, HTC
|
||||
location ~* \.(?:jpg|jpeg|gif|png|webp|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||
expires 1M;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
# CSS and Javascript
|
||||
location ~* \.(?:css|js)$ {
|
||||
expires 1y;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
location ~* \.(html)$ {
|
||||
expires -1;
|
||||
}
|
||||
|
||||
location @addslash {
|
||||
return 301 $uri/;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
client_max_body_size 2G;
|
||||
|
||||
location ~ \.php$ {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Request-Id $x_request_id;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header Forwarded-Request-Id $x_request_id;
|
||||
fastcgi_pass php-upstream;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name;
|
||||
fastcgi_read_timeout 600;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /robots.txt { access_log off; log_not_found off; }
|
||||
}
|
87
docker/php/Dockerfile
Normal file
87
docker/php/Dockerfile
Normal file
@ -0,0 +1,87 @@
|
||||
# Based on https://github.com/dead-guru/devichan/blob/master/php-fpm/Dockerfile
|
||||
|
||||
FROM composer AS composer
|
||||
FROM php:8.1-fpm-alpine
|
||||
|
||||
RUN apk add --no-cache \
|
||||
zlib \
|
||||
zlib-dev \
|
||||
libpng \
|
||||
libpng-dev \
|
||||
libjpeg-turbo \
|
||||
libjpeg-turbo-dev \
|
||||
libwebp \
|
||||
libwebp-dev \
|
||||
libcurl \
|
||||
curl-dev \
|
||||
imagemagick \
|
||||
graphicsmagick \
|
||||
gifsicle \
|
||||
ffmpeg \
|
||||
bind-tools \
|
||||
gettext \
|
||||
gettext-dev \
|
||||
icu-dev \
|
||||
oniguruma \
|
||||
oniguruma-dev \
|
||||
libmcrypt \
|
||||
libmcrypt-dev \
|
||||
lz4-libs \
|
||||
lz4-dev \
|
||||
imagemagick-dev \
|
||||
pcre-dev \
|
||||
$PHPIZE_DEPS \
|
||||
&& docker-php-ext-configure gd \
|
||||
--with-webp=/usr/include/webp \
|
||||
--with-jpeg=/usr/include \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
gd \
|
||||
curl \
|
||||
bcmath \
|
||||
opcache \
|
||||
pdo_mysql \
|
||||
gettext \
|
||||
intl \
|
||||
mbstring \
|
||||
&& pecl update-channels \
|
||||
&& pecl install -o -f igbinary \
|
||||
&& pecl install redis \
|
||||
&& pecl install imagick \
|
||||
$$ docker-php-ext-enable \
|
||||
igbinary \
|
||||
redis \
|
||||
imagick \
|
||||
&& apk del \
|
||||
zlib-dev \
|
||||
libpng-dev \
|
||||
libjpeg-turbo-dev \
|
||||
libwebp-dev \
|
||||
curl-dev \
|
||||
gettext-dev \
|
||||
oniguruma-dev \
|
||||
libmcrypt-dev \
|
||||
lz4-dev \
|
||||
imagemagick-dev \
|
||||
pcre-dev \
|
||||
$PHPIZE_DEPS \
|
||||
&& rm -rf /var/cache/*
|
||||
RUN rmdir /var/www/html \
|
||||
&& install -d -m 744 -o www-data -g www-data /var/www \
|
||||
&& install -d -m 700 -o www-data -g www-data /var/tmp/vichan \
|
||||
&& install -d -m 700 -o www-data -g www-data /var/cache/gen-cache \
|
||||
&& install -d -m 700 -o www-data -g www-data /var/cache/template-cache
|
||||
|
||||
# Copy the bootstrap script.
|
||||
COPY ./docker/php/bootstrap.sh /usr/local/bin/bootstrap.sh
|
||||
|
||||
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
|
||||
|
||||
# Copy the actual project (use .dockerignore to exclude stuff).
|
||||
COPY . /code
|
||||
|
||||
# Install the compose depedencies.
|
||||
RUN cd /code && composer install
|
||||
|
||||
WORKDIR "/var/www"
|
||||
CMD [ "bootstrap.sh" ]
|
||||
EXPOSE 9000
|
16
docker/php/Dockerfile.profile
Normal file
16
docker/php/Dockerfile.profile
Normal file
@ -0,0 +1,16 @@
|
||||
# syntax = devthefuture/dockerfile-x
|
||||
INCLUDE ./docker/php/Dockerfile
|
||||
|
||||
RUN apk add --no-cache \
|
||||
linux-headers \
|
||||
$PHPIZE_DEPS \
|
||||
&& pecl update-channels \
|
||||
&& pecl install xdebug \
|
||||
&& docker-php-ext-enable xdebug \
|
||||
&& apk del \
|
||||
linux-headers \
|
||||
$PHPIZE_DEPS \
|
||||
&& rm -rf /var/cache/*
|
||||
|
||||
ENV XDEBUG_OUT_DIR=/var/www/xdebug_out
|
||||
CMD [ "bootstrap.sh" ]
|
87
docker/php/bootstrap.sh
Executable file
87
docker/php/bootstrap.sh
Executable file
@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
function set_cfg() {
|
||||
if [ -L "/var/www/inc/$1" ]; then
|
||||
echo "INFO: Resetting $1"
|
||||
rm "/var/www/inc/$1"
|
||||
cp "/code/inc/$1" "/var/www/inc/$1"
|
||||
chown www-data "/var/www/inc/$1"
|
||||
chgrp www-data "/var/www/inc/$1"
|
||||
chmod 600 "/var/www/inc/$1"
|
||||
else
|
||||
echo "INFO: Using existing $1"
|
||||
fi
|
||||
}
|
||||
|
||||
if ! mountpoint -q /var/www; then
|
||||
echo "WARNING: '/var/www' is not a mountpoint. All the data will remain inside the container!"
|
||||
fi
|
||||
|
||||
if [ ! -w /var/www ] ; then
|
||||
echo "ERROR: '/var/www' is not writable. Closing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${XDEBUG_OUT_DIR:-''}" ] ; then
|
||||
echo "INFO: Initializing xdebug out directory at $XDEBUG_OUT_DIR"
|
||||
mkdir -p "$XDEBUG_OUT_DIR"
|
||||
chown www-data "$XDEBUG_OUT_DIR"
|
||||
chgrp www-data "$XDEBUG_OUT_DIR"
|
||||
chmod 755 "$XDEBUG_OUT_DIR"
|
||||
fi
|
||||
|
||||
# Link the entrypoints from the exposed directory.
|
||||
ln -nfs \
|
||||
/code/tools/ \
|
||||
/code/*.php \
|
||||
/code/LICENSE.* \
|
||||
/code/install.sql \
|
||||
/var/www/
|
||||
# Static files accessible from the webserver must be copied.
|
||||
cp -ur /code/static /var/www/
|
||||
cp -ur /code/stylesheets /var/www/
|
||||
|
||||
# Ensure correct permissions are set, since this might be bind mount.
|
||||
chown www-data /var/www
|
||||
chgrp www-data /var/www
|
||||
|
||||
# Initialize an empty robots.txt with the default if it doesn't exist.
|
||||
touch /var/www/robots.txt
|
||||
|
||||
# Link the cache and tmp files directory.
|
||||
ln -nfs /var/tmp/vichan /var/www/tmp
|
||||
|
||||
# Link the javascript directory.
|
||||
ln -nfs /code/js /var/www/
|
||||
|
||||
# Link the html templates directory and it's cache.
|
||||
ln -nfs /code/templates /var/www/
|
||||
ln -nfs -T /var/cache/template-cache /var/www/templates/cache
|
||||
chown -h www-data /var/www/templates/cache
|
||||
chgrp -h www-data /var/www/templates/cache
|
||||
|
||||
# Link the generic cache.
|
||||
ln -nfs -T /var/cache/gen-cache /var/www/tmp/cache
|
||||
chown -h www-data /var/www/tmp/cache
|
||||
chgrp -h www-data /var/www/tmp/cache
|
||||
|
||||
# Create the included files directory and link them
|
||||
install -d -m 700 -o www-data -g www-data /var/www/inc
|
||||
for file in /code/inc/*; do
|
||||
file="${file##*/}"
|
||||
if [ ! -e /var/www/inc/$file ]; then
|
||||
ln -s /code/inc/$file /var/www/inc/
|
||||
fi
|
||||
done
|
||||
|
||||
# Copy an empty instance configuration if the file is a link (it was linked because it did not exist before).
|
||||
set_cfg 'instance-config.php'
|
||||
set_cfg 'secrets.php'
|
||||
|
||||
# Link the composer dependencies.
|
||||
ln -nfs /code/vendor /var/www/
|
||||
|
||||
# Start the php-fpm server.
|
||||
exec php-fpm
|
2
docker/php/jit.ini
Normal file
2
docker/php/jit.ini
Normal file
@ -0,0 +1,2 @@
|
||||
opcache.jit_buffer_size=192M
|
||||
opcache.jit=tracing
|
13
docker/php/www.conf
Normal file
13
docker/php/www.conf
Normal file
@ -0,0 +1,13 @@
|
||||
[www]
|
||||
access.log = /proc/self/fd/2
|
||||
|
||||
; Ensure worker stdout and stderr are sent to the main error log.
|
||||
catch_workers_output = yes
|
||||
decorate_workers_output = no
|
||||
|
||||
user = www-data
|
||||
group = www-data
|
||||
|
||||
listen = 127.0.0.1:9000
|
||||
pm = static
|
||||
pm.max_children = 16
|
7
docker/php/xdebug-prof.ini
Normal file
7
docker/php/xdebug-prof.ini
Normal file
@ -0,0 +1,7 @@
|
||||
zend_extension=xdebug
|
||||
|
||||
[xdebug]
|
||||
xdebug.mode = profile
|
||||
xdebug.start_with_request = start
|
||||
error_reporting = E_ALL
|
||||
xdebug.output_dir = /var/www/xdebug_out
|
@ -11,12 +11,14 @@ $twig = false;
|
||||
function load_twig() {
|
||||
global $twig, $config;
|
||||
|
||||
$cache_dir = "{$config['dir']['template']}/cache/";
|
||||
|
||||
$loader = new Twig\Loader\FilesystemLoader($config['dir']['template']);
|
||||
$loader->setPaths($config['dir']['template']);
|
||||
$twig = new Twig\Environment($loader, array(
|
||||
'autoescape' => false,
|
||||
'cache' => is_writable('templates') || (is_dir('templates/cache') && is_writable('templates/cache')) ?
|
||||
new Twig_Cache_TinyboardFilesystem("{$config['dir']['template']}/cache") : false,
|
||||
'cache' => is_writable('templates/') || (is_dir($cache_dir) && is_writable($cache_dir)) ?
|
||||
new Twig_Cache_TinyboardFilesystem($cache_dir) : false,
|
||||
'debug' => $config['debug'],
|
||||
'auto_reload' => $config['twig_auto_reload']
|
||||
));
|
||||
@ -28,17 +30,17 @@ function load_twig() {
|
||||
|
||||
function Element($templateFile, array $options) {
|
||||
global $config, $debug, $twig, $build_pages;
|
||||
|
||||
|
||||
if (!$twig)
|
||||
load_twig();
|
||||
|
||||
|
||||
if (function_exists('create_pm_header') && ((isset($options['mod']) && $options['mod']) || isset($options['__mod'])) && !preg_match('!^mod/!', $templateFile)) {
|
||||
$options['pm'] = create_pm_header();
|
||||
}
|
||||
|
||||
|
||||
if (isset($options['body']) && $config['debug']) {
|
||||
$_debug = $debug;
|
||||
|
||||
|
||||
if (isset($debug['start'])) {
|
||||
$_debug['time']['total'] = '~' . round((microtime(true) - $_debug['start']) * 1000, 2) . 'ms';
|
||||
$_debug['time']['init'] = '~' . round(($_debug['start_debug'] - $_debug['start']) * 1000, 2) . 'ms';
|
||||
@ -56,15 +58,15 @@ function Element($templateFile, array $options) {
|
||||
str_replace("\n", '<br/>', utf8tohtml(print_r($_debug, true))) .
|
||||
'</pre>';
|
||||
}
|
||||
|
||||
|
||||
// Read the template file
|
||||
if (@file_get_contents("{$config['dir']['template']}/${templateFile}")) {
|
||||
$body = $twig->render($templateFile, $options);
|
||||
|
||||
|
||||
if ($config['minify_html'] && preg_match('/\.html$/', $templateFile)) {
|
||||
$body = trim(preg_replace("/[\t\r\n]/", '', $body));
|
||||
}
|
||||
|
||||
|
||||
return $body;
|
||||
} else {
|
||||
throw new Exception("Template file '${templateFile}' does not exist or is empty in '{$config['dir']['template']}'!");
|
||||
@ -102,7 +104,7 @@ class Tinyboard extends Twig\Extension\AbstractExtension
|
||||
new Twig\TwigFilter('cloak_mask', 'cloak_mask'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
@ -122,7 +124,7 @@ class Tinyboard extends Twig\Extension\AbstractExtension
|
||||
new Twig\TwigFunction('link_for', 'link_for')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
@ -154,7 +156,7 @@ function twig_hasPermission_filter($mod, $permission, $board = null) {
|
||||
function twig_extension_filter($value, $case_insensitive = true) {
|
||||
$ext = mb_substr($value, mb_strrpos($value, '.') + 1);
|
||||
if($case_insensitive)
|
||||
$ext = mb_strtolower($ext);
|
||||
$ext = mb_strtolower($ext);
|
||||
return $ext;
|
||||
}
|
||||
|
||||
@ -179,7 +181,7 @@ function twig_filename_truncate_filter($value, $length = 30, $separator = '…')
|
||||
$value = strrev($value);
|
||||
$array = array_reverse(explode(".", $value, 2));
|
||||
$array = array_map("strrev", $array);
|
||||
|
||||
|
||||
$filename = &$array[0];
|
||||
$extension = isset($array[1]) ? $array[1] : false;
|
||||
|
||||
|
10
install.php
10
install.php
@ -5,6 +5,11 @@ define('VERSION', '5.1.4');
|
||||
require 'inc/bootstrap.php';
|
||||
loadConfig();
|
||||
|
||||
if (!is_writable('inc/secrets.php') || !is_writable('inc/')) {
|
||||
echo 'install.php does not have permission to write to /inc/secrets.php and/or /inc/, without permission the installer cannot continue';
|
||||
exit();
|
||||
}
|
||||
|
||||
// Salt generators
|
||||
class SaltGen {
|
||||
public $salt_length = 128;
|
||||
@ -856,14 +861,14 @@ if ($step == 0) {
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd() . '/templates/cache',
|
||||
'result' => is_writable('templates') || (is_dir('templates/cache') && is_writable('templates/cache')),
|
||||
'result' => is_dir('templates/cache/') && is_writable('templates/cache/'),
|
||||
'required' => true,
|
||||
'message' => 'You must give vichan permission to create (and write to) the <code>templates/cache</code> directory or performance will be drastically reduced.'
|
||||
),
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd() . '/tmp/cache',
|
||||
'result' => is_dir('tmp/cache') && is_writable('tmp/cache'),
|
||||
'result' => is_dir('tmp/cache/') && is_writable('tmp/cache/'),
|
||||
'required' => true,
|
||||
'message' => 'You must give vichan permission to write to the <code>tmp/cache</code> directory.'
|
||||
),
|
||||
@ -1036,4 +1041,3 @@ if ($step == 0) {
|
||||
|
||||
echo Element('page.html', $page);
|
||||
}
|
||||
|
||||
|
1
templates/cache/.gitkeep
vendored
1
templates/cache/.gitkeep
vendored
@ -1 +0,0 @@
|
||||
|
Loading…
Reference in New Issue
Block a user