diff --git a/.docker/release/Dockerfile b/.docker/release/Dockerfile index 0e6473191..d6675462e 100644 --- a/.docker/release/Dockerfile +++ b/.docker/release/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 -FROM alpine:3.24.3 AS builder -RUN apk add --no-cache php85 php85-json php-phar php-zip +FROM alpine:3.18.5 AS builder +RUN apk add --no-cache php82 php82-json php-phar php-zip RUN apk add --no-cache npm RUN npm install -g gulp yarn WORKDIR /source @@ -23,7 +23,7 @@ RUN set -eux; \ rm -v /snappymail/README.md /snappymail/_include.php # Inspired by the original Rainloop dockerfile from youtous on GitLab -FROM php:8.5-fpm-alpine AS final +FROM php:8.2-fpm-alpine AS final LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm on Alpine" @@ -99,6 +99,9 @@ RUN set -eux; \ # mysql RUN docker-php-ext-install pdo_mysql +# opcache +RUN docker-php-ext-install opcache + # postgres RUN set -eux; \ apk add --no-cache postgresql-libs; \ @@ -119,13 +122,6 @@ RUN set -eux; \ apk del .build-dependencies; \ apk del .deps -# sqlite -RUN set -eux; \ - apk add --no-cache sqlite-libs; \ - apk add --no-cache --virtual .deps sqlite-dev; \ - docker-php-ext-install pdo_sqlite; \ - apk del .deps - # tidy RUN set -eux; \ apk add --no-cache tidyhtml; \ diff --git a/.docker/release/files/entrypoint.sh b/.docker/release/files/entrypoint.sh index c0ed7df0c..75e82d729 100755 --- a/.docker/release/files/entrypoint.sh +++ b/.docker/release/files/entrypoint.sh @@ -9,12 +9,6 @@ UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE:-25M} MEMORY_LIMIT=${MEMORY_LIMIT:-128M} SECURE_COOKIES=${SECURE_COOKIES:-true} -# Disable listening on ipv6 for ipv4-only environments, or nginx will fail to start -if ! ip a | grep 'inet6 ' > /dev/null; then - echo "[INFO] ipv6 is disabled. Configuring nginx to not listen on ipv6" - sed -i '/listen \[::\]:/d' /etc/nginx/nginx.conf -fi - # Set attachment size limit sed -i "s//$UPLOAD_MAX_SIZE/g" /usr/local/etc/php-fpm.d/php-fpm.conf /etc/nginx/nginx.conf sed -i "s//$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.d/php-fpm.conf diff --git a/SECURITY.md b/SECURITY.md index 11d1ddada..faaba8d68 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,5 +36,5 @@ YMXQVq4SJt7UpWABAORudfJxsBqCRKtPlZMgGTJLjcOkyFJ9C2Fx7DeN0J4I ## Publishing and Credits I will analyze and fix the reported issue as fast as possible. -Together with the reporter, I plan the disclosure of the found and fixed vulnerability. +Together with the reporter I plan the disclosure of the found and fixed vulnerability. Credits to the reporter are granted and can be included in all public communication if desired. diff --git a/cli/compile.php b/cli/compile.php deleted file mode 100755 index 936643cc3..000000000 --- a/cli/compile.php +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/php -{'use strict';var aa="function"==typeof Object.defineProperties?Object.defineProperty:function(C,F,E){if(C==Array.prototype||C==Object.prototype)return C;C[F]=E.value;return C};function ba(C){C=["object"==typeof globalThis&&globalThis,C,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var F=0;FE&&(E=Math.max(E+S,0));E'); - // ECMASCRIPT_202 - $data = substr($data, 0, $p1) . substr($data, $p1 + 6, -6) . "\n"; - // ECMASCRIPT_2018 -// $data = substr($data, 0, $p1) . substr($data, $p1 + 19, -6) . "\n"; - // ECMASCRIPT6 -// $data = substr($data, 0, $p1) . substr($data, strpos($data, 'return!0}return!1}});') + 22, -6) . "\n"; - - file_put_contents($file, $data); - exit; -} - -if (isset($options['openpgp'])) { - chdir(ROOT_DIR . '/vendors/openpgp-5'); - execCmd('git pull', $return_var); - execCmd('./build.sh', $return_var); - exit; -} - -if (isset($options['squire'])) { - chdir(ROOT_DIR . '/vendors/squire2'); -// execCmd('git pull', $return_var); -// execCmd('git checkout snappymail', $return_var); - execCmd('./build.sh', $return_var); - exit; -} - -if (isset($options['source'])) { - #cd ROOT_DIR . '/vendors/openpgp-2.6.2/'; - #rollup -c - #npm cache clean --force - - if ($gulp = trim(`which gulp`)) { - execCmd($gulp, $return_var); - } else { - exit('gulp not installed, run as root: npm install --global gulp-cli'); - } - - #rollup -c - - $cmddir = escapeshellcmd(ROOT_DIR) . '/snappymail/v/0.0.0/static'; - - if ($gzip = trim(`which gzip`)) { - echo "\x1b[33;1m === Gzip *.js and *.css === \x1b[0m\n"; -// execCmd("{$gzip} -k --best {$cmddir}/js/*.js"); - execCmd("{$gzip} -k --best {$cmddir}/js/min/*.js"); - execCmd("{$gzip} -k --best {$cmddir}/css/admin*.css"); - execCmd("{$gzip} -k --best {$cmddir}/css/app*.css"); -// unlink($cmddir . '/js/boot.js.gz'); -// unlink($cmddir . '/js/min/boot.min.js.gz'); - } - - if ($brotli = trim(`which brotli`)) { - echo "\x1b[33;1m === Brotli *.js and *.css === \x1b[0m\n"; -// execCmd("{$brotli} -k --best {$cmddir}/js/*.js"); - execCmd("{$brotli} -k --best {$cmddir}/js/min/*.js"); - execCmd("{$brotli} -k --best {$cmddir}/css/admin*.css"); - execCmd("{$brotli} -k --best {$cmddir}/css/app*.css"); -// unlink($cmddir . '/js/boot.js.br'); -// unlink($cmddir . '/js/min/boot.min.js.br'); - } -} - -if (isset($options['readme'])) { - - $basedir = escapeshellcmd(ROOT_DIR) . '/snappymail/v/0.0.0'; - - $readme = file_get_contents(ROOT_DIR . '/README.md'); - - $total = filesize("{$basedir}/static/js/serviceworker.js"); - foreach (['admin','app','boot','libs','sieve'] as $name) { - $size = filesize("{$basedir}/static/js/{$name}.js"); - $total += $size; - $readme = preg_replace("/(\\|{$name}\\.js\\s+\\|[\\s0-9.]+\\|)[\\s0-9.]+\\|/Ds", - '$1' . str_pad(number_format($size, 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' |', - $readme - ); - } - $readme = preg_replace("/(\\|TOTAL\\s+\\|8[\\s0-9.]+\\|)[\\s0-9.]+\\|/Ds", - '$1' . str_pad(number_format($total, 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' |', - $readme - ); - - $total = []; - $total_br = []; - $total_gz = []; - foreach (['admin','app','boot','libs','sieve'] as $name) { - $size = filesize("{$basedir}/static/js/min/{$name}.min.js"); - $size_br = filesize("{$basedir}/static/js/min/{$name}.min.js.br"); - $size_gz = filesize("{$basedir}/static/js/min/{$name}.min.js.gz"); - $total[$name] = $size; - $total_br[$name] = $size_br; - $total_gz[$name] = $size_gz; - $readme = preg_replace( - "/(\\|{$name}\\.min\\.js\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format($size, 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format($size_gz, 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$3|' - . str_pad(number_format($size_br, 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - } - $readme = preg_replace( - "/(TOTAL user\+sieve\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format(array_sum($total) - $total['admin'], 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format(array_sum($total_gz) - $total_gz['admin'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$3|' - . str_pad(number_format(array_sum($total_br) - $total_br['admin'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - - //$smaller = 1217635 / (array_sum($total) - $total['admin']); - $smaller = 358761 / (array_sum($total_gz) - $total_gz['admin']); - //$smaller = 299485 / (array_sum($total_br) - $total_br['admin']); - $readme = preg_replace( - '/(For a user it is around) [0-9]+/', - '$1 ' . round(100 - 100 / $smaller), - $readme - ); - - unset($total['sieve']); - unset($total_br['sieve']); - unset($total_gz['sieve']); - $readme = preg_replace( - "/(TOTAL user\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format(array_sum($total) - $total['admin'], 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format(array_sum($total_gz) - $total_gz['admin'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$3|' - . str_pad(number_format(array_sum($total_br) - $total_br['admin'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - $readme = preg_replace( - "/(TOTAL admin\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format(array_sum($total) - $total['app'], 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format(array_sum($total_gz) - $total_gz['app'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$3|' - . str_pad(number_format(array_sum($total_br) - $total_br['app'], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - - foreach (['admin','app'] as $name) { - $readme = preg_replace( - "/(\\|{$name}\\.css\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.css"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.css.gz"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' |' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.css.br"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - $readme = preg_replace( - "/(\\|{$name}\\.min\\.css\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.min.css"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$2|' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.min.css.gz"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' |' - . str_pad(number_format(filesize("{$basedir}/static/css/{$name}.min.css.br"), 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - } - - - $sizes = [ - filesize("{$basedir}/static/js/min/openpgp.min.js"), - filesize("{$basedir}/static/js/min/openpgp.min.js.gz"), - filesize("{$basedir}/static/js/min/openpgp.min.js.br") - ]; - //|openpgp.min.js | 330.742 | 540.542 |102.388 | 167.397 | 84.241 | 137.502 | - $readme = preg_replace( - "/(openpgp\.min\.js\\s+\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+(\\|[\\s0-9.]+)\\|[\\s0-9.]+\\|/Ds", - '$1|' - . str_pad(number_format($sizes[0], 0, '', '.'), 9, ' ', STR_PAD_LEFT) . ' ' - . '$2| ' - . str_pad(number_format($sizes[1], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '$3| ' - . str_pad(number_format($sizes[2], 0, '', '.'), 7, ' ', STR_PAD_LEFT) . ' ' - . '|' - , - $readme - ); - - //file:// - - file_put_contents(ROOT_DIR . '/README.md', $readme); - - $data = file_put_contents( - "{$basedir}/app/templates/Views/Admin/AdminSettingsAbout.html", - preg_replace( - '/20[0-9][0-9] ©/', - date('Y').' ©', - file_get_contents("{$basedir}/app/templates/Views/Admin/AdminSettingsAbout.html") - ) - ); -} diff --git a/cli/release.php b/cli/release.php index fe406f7f3..aac915b02 100755 --- a/cli/release.php +++ b/cli/release.php @@ -9,7 +9,7 @@ if (isset($options['plugins'])) { require(ROOT_DIR . '/build/plugins.php'); } -$gulp = trim(shell_exec('which gulp')); +$gulp = trim(`which gulp`); if (!$gulp) { exit('gulp not installed, run as root: npm install --global gulp-cli'); } @@ -34,7 +34,7 @@ $options['aur'] = isset($options['aur']); // Docker build $options['docker'] = isset($options['docker']); -if ($options['docker'] && !($docker = trim(shell_exec('which docker')))) { +if ($options['docker'] && !($docker = trim(`which docker`))) { exit('docker not found'); } if ($options['docker'] && $options['aur']) { @@ -60,7 +60,7 @@ if (!isset($options['skip-gulp'])) { $cmddir = escapeshellcmd(ROOT_DIR) . '/snappymail/v/0.0.0/static'; - if ($gzip = trim(shell_exec('which gzip'))) { + if ($gzip = trim(`which gzip`)) { echo "\x1b[33;1m === Gzip *.js and *.css === \x1b[0m\n"; passthru("{$gzip} -k --best {$cmddir}/js/*.js"); passthru("{$gzip} -k --best {$cmddir}/js/min/*.js"); @@ -70,7 +70,7 @@ if (!isset($options['skip-gulp'])) { unlink(ROOT_DIR . '/snappymail/v/0.0.0/static/js/min/boot.min.js.gz'); } - if ($brotli = trim(shell_exec('which brotli'))) { + if ($brotli = trim(`which brotli`)) { echo "\x1b[33;1m === Brotli *.js and *.css === \x1b[0m\n"; passthru("{$brotli} -k --best {$cmddir}/js/*.js"); passthru("{$brotli} -k --best {$cmddir}/js/min/*.js"); @@ -188,7 +188,7 @@ file_put_contents("{$destPath}core.json", '{ // Arch User Repository if ($options['aur']) { // extension_loaded('blake2') - if (!function_exists('b2sum') && $b2sum = trim(shell_exec('which b2sum'))) { + if (!function_exists('b2sum') && $b2sum = trim(`which b2sum`)) { function b2sum($file) { $file = escapeshellarg($file); exec("b2sum --binary {$file} 2>&1", $output, $exitcode); diff --git a/dev/App/User.js b/dev/App/User.js index 5e28164ac..aafec7da3 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -1,7 +1,6 @@ import 'External/User/ko'; import { SMAudio } from 'Common/Audio'; -import { arrayLength } from 'Common/Utils'; import { mailToHelper, setLayoutResizer, dropdownsDetectVisibility, loadAccountsAndIdentities } from 'Common/UtilsUser'; import { @@ -241,15 +240,7 @@ export class AppUser extends AbstractApp { showMessageComposer(params = []) { - let msg = params[1]; - if (1 == arrayLength(msg)) { - msg = msg[0]; - } - if (msg) { - msg.decrypt().then((/*success*/)=>showScreenPopup(ComposePopupView, params)); - } else { - showScreenPopup(ComposePopupView, params); - } + showScreenPopup(ComposePopupView, params); } } @@ -260,8 +251,7 @@ AskPopupView.password = function(sAskDesc, btnText, ask) { view => resolve({ password:view.passphrase(), username:/*ask & 2 ? */view.username(), - remember:/*ask & 4 ? */view.remember(), - rememberPermanent: view.rememberPermanent(), + remember:/*ask & 4 ? */view.remember() }), () => resolve(null), true, diff --git a/dev/Common/Html.js b/dev/Common/Html.js index d495a8c31..0be300ec9 100644 --- a/dev/Common/Html.js +++ b/dev/Common/Html.js @@ -232,7 +232,6 @@ export const detectHiddenImages = true, // !!SettingsGet('try_to_detect_hidden_images'), bqLevel = parseInt(SettingsUserStore.maxBlockquotesLevel()), - minFontSize = parseInt(SettingsUserStore.minFontSize()), result = { hasExternals: false, @@ -258,15 +257,6 @@ export const rightmargin: (value, node) => node.style.marginRight = pInt(value) + 'px' }, allowedAttributes = [ - // SnappyMail -// 'data-x-href-broken', -// 'data-x-href-tracking', - 'data-x-src', -// 'data-x-src-hidden', -// 'data-x-src-tracking', -// 'data-x-src-broken', -// 'data-x-style-url', -// 'data-x-style-broken-urls', // defaults 'name', 'dir', 'lang', 'style', 'title', @@ -309,11 +299,8 @@ export const // Not supported by