Compare commits
110 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
87214fef70 | ||
|
f1f9626b5b | ||
|
3a13c93022 | ||
|
83bd66db98 | ||
|
13175b4e6c | ||
|
ecefbf2166 | ||
|
a763dda068 | ||
|
698b2bf988 | ||
|
802d304579 | ||
|
8614d63ace | ||
|
6d8c978d17 | ||
|
ff4f2ae0b6 | ||
|
0b00f15811 | ||
|
bed5218550 | ||
|
86b67a9a7b | ||
|
73370de1f9 | ||
|
524aba0964 | ||
|
64528d8e0e | ||
|
31b5faa729 | ||
|
17977a2fff | ||
|
3e007eeaae | ||
|
05b897f43e | ||
|
738dcac60d | ||
|
b3bbeee5e2 | ||
|
782eae4d4c | ||
|
f2f5e212f5 | ||
|
ff7102468e | ||
|
118cb1017a | ||
|
360bb6f306 | ||
|
d8e314db1a | ||
|
fd14c51f85 | ||
|
57a5a9baeb | ||
|
65c74c75c7 | ||
|
e82f3b3975 | ||
|
fbc33da734 | ||
|
210815d4cf | ||
|
1e672ae349 | ||
|
046e658984 | ||
|
a46db9e0df | ||
|
17f3cc3ad8 | ||
|
3236a10cf5 | ||
|
a4eb6d5f1b | ||
|
05181f1888 | ||
|
6875baf64c | ||
|
c46a1c1e2f | ||
|
b79a1530fb | ||
|
a6a7ab45f8 | ||
|
bc937ed2db | ||
|
df17e6b75e | ||
|
f880e1834d | ||
|
4dd1b97e38 | ||
|
aeb433cc39 | ||
|
eb9d360c0a | ||
|
abfad4e025 | ||
|
e9091cbb8c | ||
|
cb340d78e1 | ||
|
548d7b9833 | ||
|
96dbbf4db6 | ||
|
4f14462af7 | ||
|
1e08b4ece6 | ||
|
6fd9efc30a | ||
|
6f212a41d8 | ||
|
52314d1a35 | ||
|
3028a18a37 | ||
|
26a5fcf989 | ||
|
509086ef54 | ||
|
963510ed22 | ||
|
2c0f8cda50 | ||
|
50d2671d75 | ||
|
b73d879f3c | ||
|
725a5fe5b9 | ||
|
65ca42ca42 | ||
|
b22ff59f7b | ||
|
58527857d9 | ||
|
6306c4555c | ||
|
922603f906 | ||
|
f8d45de749 | ||
|
cb1602c2de | ||
|
8026b6c874 | ||
|
042676fff7 | ||
|
44d53146af | ||
|
ce4fb069d5 | ||
|
9444000d46 | ||
|
eacd9ac240 | ||
|
cf38d6ca69 | ||
|
905993d66e | ||
|
0d7fe2e347 | ||
|
33bd871a63 | ||
|
772122b255 | ||
|
9fb346751c | ||
|
cb058e91a3 | ||
|
27e7407407 | ||
|
623397d20a | ||
|
7d46de33d8 | ||
|
f34d3620b1 | ||
|
70e99447f9 | ||
|
7b57b3392c | ||
|
492451bfee | ||
|
a1e8077f45 | ||
|
956e4e2aa7 | ||
|
c2e0a275e1 | ||
|
514079fe96 | ||
|
27e9210d52 | ||
|
1b6e5b7116 | ||
|
0dab215e27 | ||
|
6ec136e63f | ||
|
bba5671eaf | ||
|
88d7593d89 | ||
|
bd23b80d45 | ||
|
f96e0c4071 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
custom: https://mailcow.github.io/mailcow-dockerized-docs/#help-mailcow
|
||||
custom: ["https://www.servercow.de/mailcow?lang=en#sal"]
|
||||
|
166
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
166
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
@@ -7,8 +7,8 @@ body:
|
||||
label: Contribution guidelines
|
||||
description: Please read the contribution guidelines before proceeding.
|
||||
options:
|
||||
- label: I've read the [contribution guidelines](https://github.com/mailcow/mailcow-dockerized/blob/master/CONTRIBUTING.md) and wholeheartedly agree
|
||||
required: true
|
||||
- label: I've read the [contribution guidelines](https://github.com/mailcow/mailcow-dockerized/blob/master/CONTRIBUTING.md) and wholeheartedly agree
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: I've found a bug and checked that ...
|
||||
@@ -26,70 +26,132 @@ body:
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide a brief description of the bug in 1-2 sentences. If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI.
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
description: Please take a look at the [official documentation](https://mailcow.github.io/mailcow-dockerized-docs/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks.
|
||||
render: bash
|
||||
label: "Logs:"
|
||||
description: "Please take a look at the [official documentation](https://docs.mailcow.email/troubleshooting/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks."
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please describe the steps to reproduce the bug. Screenshots can be added, if helpful.
|
||||
label: "Steps to reproduce:"
|
||||
description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful."
|
||||
render: text
|
||||
placeholder: |-
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
- type: markdown
|
||||
attributes:
|
||||
label: System information
|
||||
description: In this stage we would kindly ask you to attach general system information about your setup.
|
||||
value: |-
|
||||
| Question | Answer |
|
||||
| --- | --- |
|
||||
| My operating system | I_DO_REPLY_HERE |
|
||||
| Is Apparmor, SELinux or similar active? | I_DO_REPLY_HERE |
|
||||
| Virtualization technology (KVM, VMware, Xen, etc - **LXC and OpenVZ are not supported** | I_DO_REPLY_HERE |
|
||||
| Server/VM specifications (Memory, CPU Cores) | I_DO_REPLY_HERE |
|
||||
| Docker version (`docker version`) | I_DO_REPLY_HERE |
|
||||
| docker-compose version (`docker-compose version`) | I_DO_REPLY_HERE |
|
||||
| mailcow version (```git describe --tags `git rev-list --tags --max-count=1` ```) | I_DO_REPLY_HERE |
|
||||
| Reverse proxy (custom solution) | I_DO_REPLY_HERE |
|
||||
|
||||
Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
|
||||
All third-party firewalls and custom iptables rules are unsupported. **Please check the Docker docs about how to use Docker with your own ruleset**. Nevertheless, iptabels output can help us to help you:
|
||||
iptables -L -vn:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
|
||||
ip6tables -L -vn:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
|
||||
iptables -L -vn -t nat:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
|
||||
ip6tables -L -vn -t nat:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
|
||||
DNS problems? Please run `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @172.22.1.254` (set the IP accordingly, if you changed the internal mailcow network) and post the output:
|
||||
```
|
||||
YOUR OUTPUT GOES HERE
|
||||
```
|
||||
value: |
|
||||
## System information
|
||||
### In this stage we would kindly ask you to attach general system information about your setup.
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: "Which branch are you using?"
|
||||
description: "#### `git rev-parse --abbrev-ref HEAD`"
|
||||
multiple: false
|
||||
options:
|
||||
- master
|
||||
- nightly
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Operating System:"
|
||||
placeholder: "e.g. Ubuntu 22.04 LTS"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Server/VM specifications:"
|
||||
placeholder: "Memory, CPU Cores"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Is Apparmor, SELinux or similar active?"
|
||||
placeholder: "yes/no"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Virtualization technology:"
|
||||
placeholder: "KVM, VMware, Xen, etc - **LXC and OpenVZ are not supported**"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Docker version:"
|
||||
description: "#### `docker version`"
|
||||
placeholder: "20.10.21"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "docker-compose version or docker compose version:"
|
||||
description: "#### `docker-compose version` or `docker compose version`"
|
||||
placeholder: "v2.12.2"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "mailcow version:"
|
||||
description: "#### ```git describe --tags `git rev-list --tags --max-count=1` ```"
|
||||
placeholder: "2022-08"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Reverse proxy:"
|
||||
placeholder: "e.g. Nginx/Traefik"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Logs of git diff:"
|
||||
description: "#### Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Logs of iptables -L -vn:"
|
||||
description: "#### Output of `iptables -L -vn`"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Logs of ip6tables -L -vn:"
|
||||
description: "#### Output of `ip6tables -L -vn`"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Logs of iptables -L -vn -t nat:"
|
||||
description: "#### Output of `iptables -L -vn -t nat`"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Logs of ip6tables -L -vn -t nat:"
|
||||
description: "#### Output of `ip6tables -L -vn -t nat`"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "DNS check:"
|
||||
description: "#### Output of `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @172.22.1.254` (set the IP accordingly, if you changed the internal mailcow network)"
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
|
13
.github/ISSUE_TEMPLATE/pr_to_nighty_template.yml
vendored
Normal file
13
.github/ISSUE_TEMPLATE/pr_to_nighty_template.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
## :memo: Brief description
|
||||
<!-- Diff summary - START -->
|
||||
<!-- Diff summary - END -->
|
||||
|
||||
|
||||
## :computer: Commits
|
||||
<!-- Diff commits - START -->
|
||||
<!-- Diff commits - END -->
|
||||
|
||||
|
||||
## :file_folder: Modified files
|
||||
<!-- Diff files - START -->
|
||||
<!-- Diff files - END -->
|
BIN
.github/workflows/assets/check_prs_if_on_staging.png
vendored
Normal file
BIN
.github/workflows/assets/check_prs_if_on_staging.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
33
.github/workflows/check_prs_if_on_staging.yml
vendored
Normal file
33
.github/workflows/check_prs_if_on_staging.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Check PRs if on staging
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, edited]
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
is_not_staging:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging
|
||||
steps:
|
||||
- name: Send message
|
||||
uses: thollander/actions-comment-pull-request@main
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }}
|
||||
message: |
|
||||
Thanks for contributing!
|
||||
|
||||
I noticed that you didn't select `staging` as your base branch. Please change the base branch to `staging`.
|
||||
See the attached picture on how to change the base branch to `staging`:
|
||||
|
||||

|
||||
|
||||
- name: Fail #we want to see failed checks in the PR
|
||||
if: ${{ success() }} #set exit code to 1 even if commenting somehow failed
|
||||
run: exit 1
|
||||
|
||||
is_staging:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.base.ref == 'staging' #check if the target branch is staging
|
||||
steps:
|
||||
- name: Success
|
||||
run: exit 0
|
@@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Mark/Close Stale Issues and Pull Requests 🗑️
|
||||
uses: actions/stale@v6.0.0
|
||||
uses: actions/stale@v6.0.1
|
||||
with:
|
||||
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
||||
days-before-stale: 60
|
||||
|
25
.github/workflows/pr_to_nightly.yml
vendored
Normal file
25
.github/workflows/pr_to_nightly.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Create PR to merge to nightly from staging
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- staging
|
||||
jobs:
|
||||
action-pull-request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run the Action
|
||||
uses: devops-infra/action-pull-request@v0.5.3
|
||||
with:
|
||||
github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
|
||||
title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}
|
||||
assignee: DerLinkman
|
||||
source_branch: staging
|
||||
target_branch: nightly
|
||||
reviewer: DerLinkman
|
||||
label: upstream
|
||||
template: .github/ISSUE_TEMPLATE/pr_to_nighty_template.yml
|
||||
get_diff: true
|
34
.github/workflows/rebuild_backup_image.yml
vendored
Normal file
34
.github/workflows/rebuild_backup_image.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Build mailcow backup image
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# At 00:00 on Sunday
|
||||
- cron: "0 0 * * 0"
|
||||
workflow_dispatch: # Allow to run workflow manually
|
||||
|
||||
jobs:
|
||||
docker_image_build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: data/Dockerfiles/backup/Dockerfile
|
||||
push: true
|
||||
tags: mailcow/backup:latest
|
@@ -4,9 +4,12 @@ on:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
tweet:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Get Release Tag"
|
||||
run: |
|
||||
RELEASE_TAG=$(curl https://api.github.com/repos/mailcow/mailcow-dockerized/releases/latest | jq -r '.tag_name')
|
||||
- name: Tweet-trigger-publish-release
|
||||
uses: mugi111/tweet-trigger-release@v1.1
|
||||
with:
|
||||
@@ -14,4 +17,4 @@ jobs:
|
||||
consumer_secret: ${{ secrets.CONSUMER_SECRET }}
|
||||
access_token_key: ${{ secrets.ACCESS_TOKEN_KEY }}
|
||||
access_token_secret: ${{ secrets.ACCESS_TOKEN_SECRET }}
|
||||
tweet_body: 'A new mailcow-dockerized Release has been Released on GitHub! Checkout our GitHub Page for the latest Release: github.com/mailcow/mailcow-dockerized/releases/latest'
|
||||
tweet_body: 'A new mailcow update has just been released! Checkout the GitHub Page for changelog and more informations: https://github.com/mailcow/mailcow-dockerized/releases/latest'
|
||||
|
@@ -1,7 +1,5 @@
|
||||
# mailcow: dockerized - 🐮 + 🐋 = 💕
|
||||
|
||||
## We stand with 🇺🇦
|
||||
|
||||
[](https://github.com/mailcow/mailcow-dockerized/actions/workflows/integration_tests.yml)
|
||||
[](https://translate.mailcow.email/engage/mailcow-dockerized/)
|
||||
[](https://twitter.com/mailcow_email)
|
||||
@@ -36,3 +34,9 @@ Telegram desktop clients are available for [multiple platforms](https://desktop.
|
||||
|
||||
**Important**: mailcow makes use of various open-source software. Please assure you agree with their license before using mailcow.
|
||||
Any part of mailcow itself is released under **GNU General Public License, Version 3**.
|
||||
|
||||
mailcow is a registered word mark of The Infrastructure Company GmbH, Parkstr. 42, 47877 Willich, Germany.
|
||||
|
||||
The project is managed and maintained by The Infrastructure Company GmbH.
|
||||
|
||||
Originated from @andryyy (André)
|
3
data/Dockerfiles/backup/Dockerfile
Normal file
3
data/Dockerfiles/backup/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
RUN apt update && apt install pigz
|
@@ -51,8 +51,8 @@ sub sig_handler {
|
||||
die "sig_handler received signal, preparing to exit...\n";
|
||||
};
|
||||
|
||||
open my $file, '<', "/etc/sogo/sieve.creds";
|
||||
my $creds = <$file>;
|
||||
open my $file, '<', "/etc/sogo/sieve.creds";
|
||||
my $creds = <$file>;
|
||||
close $file;
|
||||
my ($master_user, $master_pass) = split /:/, $creds;
|
||||
my $sth = $dbh->prepare("SELECT id,
|
||||
@@ -166,17 +166,11 @@ while ($row = $sth->fetchrow_arrayref()) {
|
||||
$success = 1;
|
||||
}
|
||||
|
||||
$keep_job_active = 1;
|
||||
if (defined $exit_status && $exit_status eq "EXIT_AUTHENTICATION_FAILURE_USER1") {
|
||||
$keep_job_active = 0;
|
||||
}
|
||||
|
||||
$update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, success = ?, exit_status = ?, active = ? WHERE id = ?");
|
||||
$update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, success = ?, exit_status = ? WHERE id = ?");
|
||||
$update->bind_param( 1, ${stdout} );
|
||||
$update->bind_param( 2, ${success} );
|
||||
$update->bind_param( 3, ${exit_status} );
|
||||
$update->bind_param( 4, ${keep_job_active} );
|
||||
$update->bind_param( 5, ${id} );
|
||||
$update->bind_param( 4, ${id} );
|
||||
$update->execute();
|
||||
} catch {
|
||||
$update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync', success = 0 WHERE id = ?");
|
||||
|
@@ -252,7 +252,7 @@ def permBan(net, unban=False):
|
||||
if rule not in chain.rules and not unban:
|
||||
logCrit('Add host/network %s to blacklist' % net)
|
||||
chain.insert_rule(rule)
|
||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||
elif rule in chain.rules and unban:
|
||||
logCrit('Remove host/network %s from blacklist' % net)
|
||||
chain.delete_rule(rule)
|
||||
@@ -267,7 +267,7 @@ def permBan(net, unban=False):
|
||||
if rule not in chain.rules and not unban:
|
||||
logCrit('Add host/network %s to blacklist' % net)
|
||||
chain.insert_rule(rule)
|
||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||
elif rule in chain.rules and unban:
|
||||
logCrit('Remove host/network %s from blacklist' % net)
|
||||
chain.delete_rule(rule)
|
||||
@@ -346,6 +346,8 @@ def snat4(snat_target):
|
||||
rule.dst = '!' + rule.src
|
||||
target = rule.create_target("SNAT")
|
||||
target.to_source = snat_target
|
||||
match = rule.create_match("comment")
|
||||
match.comment = f'{int(round(time.time()))}'
|
||||
return rule
|
||||
|
||||
while not quit_now:
|
||||
@@ -356,19 +358,26 @@ def snat4(snat_target):
|
||||
table.refresh()
|
||||
chain = iptc.Chain(table, 'POSTROUTING')
|
||||
table.autocommit = False
|
||||
if get_snat4_rule() not in chain.rules:
|
||||
logCrit('Added POSTROUTING rule for source network %s to SNAT target %s' % (get_snat4_rule().src, snat_target))
|
||||
chain.insert_rule(get_snat4_rule())
|
||||
table.commit()
|
||||
else:
|
||||
for position, item in enumerate(chain.rules):
|
||||
if item == get_snat4_rule():
|
||||
if position != 0:
|
||||
chain.delete_rule(get_snat4_rule())
|
||||
table.commit()
|
||||
new_rule = get_snat4_rule()
|
||||
for position, rule in enumerate(chain.rules):
|
||||
match = all((
|
||||
new_rule.get_src() == rule.get_src(),
|
||||
new_rule.get_dst() == rule.get_dst(),
|
||||
new_rule.target.parameters == rule.target.parameters,
|
||||
new_rule.target.name == rule.target.name
|
||||
))
|
||||
if position == 0:
|
||||
if not match:
|
||||
logInfo(f'Added POSTROUTING rule for source network {new_rule.src} to SNAT target {snat_target}')
|
||||
chain.insert_rule(new_rule)
|
||||
else:
|
||||
if match:
|
||||
logInfo(f'Remove rule for source network {new_rule.src} to SNAT target {snat_target} from POSTROUTING chain at position {position}')
|
||||
chain.delete_rule(rule)
|
||||
table.commit()
|
||||
table.autocommit = True
|
||||
except:
|
||||
print('Error running SNAT4, retrying...')
|
||||
print('Error running SNAT4, retrying...')
|
||||
|
||||
def snat6(snat_target):
|
||||
global lock
|
||||
@@ -402,7 +411,7 @@ def snat6(snat_target):
|
||||
table.commit()
|
||||
table.autocommit = True
|
||||
except:
|
||||
print('Error running SNAT6, retrying...')
|
||||
print('Error running SNAT6, retrying...')
|
||||
|
||||
def autopurge():
|
||||
while not quit_now:
|
||||
@@ -468,7 +477,7 @@ def whitelistUpdate():
|
||||
if Counter(new_whitelist) != Counter(WHITELIST):
|
||||
WHITELIST = new_whitelist
|
||||
logInfo('Whitelist was changed, it has %s entries' % len(WHITELIST))
|
||||
time.sleep(60.0 - ((time.time() - start_time) % 60.0))
|
||||
time.sleep(60.0 - ((time.time() - start_time) % 60.0))
|
||||
|
||||
def blacklistUpdate():
|
||||
global quit_now
|
||||
@@ -479,7 +488,7 @@ def blacklistUpdate():
|
||||
new_blacklist = []
|
||||
if list:
|
||||
new_blacklist = genNetworkList(list)
|
||||
if Counter(new_blacklist) != Counter(BLACKLIST):
|
||||
if Counter(new_blacklist) != Counter(BLACKLIST):
|
||||
addban = set(new_blacklist).difference(BLACKLIST)
|
||||
delban = set(BLACKLIST).difference(new_blacklist)
|
||||
BLACKLIST = new_blacklist
|
||||
@@ -490,7 +499,7 @@ def blacklistUpdate():
|
||||
if delban:
|
||||
for net in delban:
|
||||
permBan(net=net, unban=True)
|
||||
time.sleep(60.0 - ((time.time() - start_time) % 60.0))
|
||||
time.sleep(60.0 - ((time.time() - start_time) % 60.0))
|
||||
|
||||
def initChain():
|
||||
# Is called before threads start, no locking
|
||||
|
@@ -1,12 +1,12 @@
|
||||
FROM php:8.0-fpm-alpine3.16
|
||||
FROM php:8.1-fpm-alpine3.16
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
ENV APCU_PECL 5.1.21
|
||||
ENV APCU_PECL 5.1.22
|
||||
ENV IMAGICK_PECL 3.7.0
|
||||
# Mailparse is pulled from master branch
|
||||
#ENV MAILPARSE_PECL 3.0.2
|
||||
ENV MAILPARSE_PECL 3.1.4
|
||||
ENV MEMCACHED_PECL 3.2.0
|
||||
ENV REDIS_PECL 5.3.7
|
||||
ENV COMPOSER 2.4.4
|
||||
|
||||
RUN apk add -U --no-cache autoconf \
|
||||
aspell-dev \
|
||||
@@ -18,6 +18,7 @@ RUN apk add -U --no-cache autoconf \
|
||||
freetype-dev \
|
||||
g++ \
|
||||
git \
|
||||
gettext \
|
||||
gettext-dev \
|
||||
gmp-dev \
|
||||
gnupg \
|
||||
@@ -27,8 +28,11 @@ RUN apk add -U --no-cache autoconf \
|
||||
imagemagick-dev \
|
||||
imap-dev \
|
||||
jq \
|
||||
libavif \
|
||||
libavif-dev \
|
||||
libjpeg-turbo \
|
||||
libjpeg-turbo-dev \
|
||||
libmemcached \
|
||||
libmemcached-dev \
|
||||
libpng \
|
||||
libpng-dev \
|
||||
@@ -38,7 +42,9 @@ RUN apk add -U --no-cache autoconf \
|
||||
libtool \
|
||||
libwebp-dev \
|
||||
libxml2-dev \
|
||||
libxpm \
|
||||
libxpm-dev \
|
||||
libzip \
|
||||
libzip-dev \
|
||||
make \
|
||||
mysql-client \
|
||||
@@ -49,22 +55,24 @@ RUN apk add -U --no-cache autoconf \
|
||||
samba-client \
|
||||
zlib-dev \
|
||||
tzdata \
|
||||
&& git clone https://github.com/php/pecl-mail-mailparse \
|
||||
&& cd pecl-mail-mailparse \
|
||||
&& pecl install package.xml \
|
||||
&& cd .. \
|
||||
&& rm -r pecl-mail-mailparse \
|
||||
&& pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} \
|
||||
&& pecl install mailparse-${MAILPARSE_PECL} \
|
||||
&& pecl install redis-${REDIS_PECL} \
|
||||
&& pecl install memcached-${MEMCACHED_PECL} \
|
||||
&& pecl install APCu-${APCU_PECL} \
|
||||
&& pecl install imagick-${IMAGICK_PECL} \
|
||||
&& docker-php-ext-enable apcu imagick memcached mailparse redis \
|
||||
&& pecl clear-cache \
|
||||
&& docker-php-ext-configure intl \
|
||||
&& docker-php-ext-configure exif \
|
||||
&& docker-php-ext-configure gd --with-freetype=/usr/include/ \
|
||||
--with-jpeg=/usr/include/ \
|
||||
--with-webp \
|
||||
--with-xpm \
|
||||
--with-avif \
|
||||
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
|
||||
&& docker-php-ext-configure imap --with-imap --with-imap-ssl \
|
||||
&& docker-php-ext-install -j 4 imap \
|
||||
&& curl --silent --show-error https://getcomposer.org/installer | php \
|
||||
&& curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER} \
|
||||
&& mv composer.phar /usr/local/bin/composer \
|
||||
&& chmod +x /usr/local/bin/composer \
|
||||
&& apk del --purge autoconf \
|
||||
@@ -72,15 +80,21 @@ RUN apk add -U --no-cache autoconf \
|
||||
cyrus-sasl-dev \
|
||||
freetype-dev \
|
||||
g++ \
|
||||
gettext-dev \
|
||||
icu-dev \
|
||||
imagemagick-dev \
|
||||
imap-dev \
|
||||
libavif-dev \
|
||||
libjpeg-turbo-dev \
|
||||
libmemcached-dev \
|
||||
libpng-dev \
|
||||
libressl-dev \
|
||||
libwebp-dev \
|
||||
libxml2-dev \
|
||||
libxpm-dev \
|
||||
libzip-dev \
|
||||
make \
|
||||
openldap-dev \
|
||||
pcre-dev \
|
||||
zlib-dev
|
||||
|
||||
|
@@ -16,8 +16,7 @@ rules {
|
||||
backend = "http";
|
||||
url = "http://nginx:9081/pushover.php";
|
||||
selector = "mailcow_rcpt";
|
||||
# Only return msgid, do not parse the full message
|
||||
formatter = "msgid";
|
||||
formatter = "json";
|
||||
meta_headers = true;
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ if (!function_exists('getallheaders')) {
|
||||
}
|
||||
|
||||
$headers = getallheaders();
|
||||
$json_body = json_decode(file_get_contents('php://input'));
|
||||
|
||||
$qid = $headers['X-Rspamd-Qid'];
|
||||
$rcpts = $headers['X-Rspamd-Rcpt'];
|
||||
@@ -65,6 +66,20 @@ if (is_array($symbols_array)) {
|
||||
}
|
||||
}
|
||||
|
||||
$sender_address = $json_body->header_from[0];
|
||||
$sender_name = '-';
|
||||
if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $sender_address, $matches)) {
|
||||
$sender_address = $matches['address'];
|
||||
$sender_name = trim($matches['name'], '"\' ');
|
||||
}
|
||||
|
||||
$to_address = $json_body->header_to[0];
|
||||
$to_name = '-';
|
||||
if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $to_address, $matches)) {
|
||||
$to_address = $matches['address'];
|
||||
$to_name = trim($matches['name'], '"\' ');
|
||||
}
|
||||
|
||||
$rcpt_final_mailboxes = array();
|
||||
|
||||
// Loop through all rcpts
|
||||
@@ -229,9 +244,16 @@ foreach ($rcpt_final_mailboxes as $rcpt_final) {
|
||||
$post_fields = array(
|
||||
"token" => $api_data['token'],
|
||||
"user" => $api_data['key'],
|
||||
"title" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $title)),
|
||||
"title" => sprintf("%s", str_replace(
|
||||
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}'),
|
||||
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address), $title)
|
||||
),
|
||||
"priority" => $priority,
|
||||
"message" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $text))
|
||||
"message" => sprintf("%s", str_replace(
|
||||
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '\n'),
|
||||
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, PHP_EOL), $text)
|
||||
),
|
||||
"sound" => $attributes['sound'] ?? "pushover"
|
||||
);
|
||||
if ($attributes['evaluate_x_prio'] == "1" && $priority == 1) {
|
||||
$post_fields['expire'] = 600;
|
||||
|
@@ -3349,6 +3349,7 @@ paths:
|
||||
evaluate_x_prio: "0"
|
||||
key: 21e8918e1jksdjcpis712
|
||||
only_x_prio: "0"
|
||||
sound: "pushover"
|
||||
senders: ""
|
||||
senders_regex: ""
|
||||
text: ""
|
||||
@@ -3392,6 +3393,7 @@ paths:
|
||||
evaluate_x_prio: "0"
|
||||
key: 21e8918e1jksdjcpis712
|
||||
only_x_prio: "0"
|
||||
sound: "pushover"
|
||||
senders: ""
|
||||
senders_regex: ""
|
||||
text: ""
|
||||
@@ -3413,6 +3415,9 @@ paths:
|
||||
only_x_prio:
|
||||
description: Only send push for prio mails
|
||||
type: number
|
||||
sound:
|
||||
description: Set notification sound
|
||||
type: string
|
||||
senders:
|
||||
description: Only send push for emails from these senders
|
||||
type: string
|
||||
@@ -5501,6 +5506,60 @@ paths:
|
||||
attr:
|
||||
spam_score: "8,15"
|
||||
summary: Edit mailbox spam filter score
|
||||
"/api/v1/get/mailbox/all/{domain}":
|
||||
get:
|
||||
parameters:
|
||||
- description: name of domain
|
||||
in: path
|
||||
name: domain
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: e.g. api-key-string
|
||||
example: api-key-string
|
||||
in: header
|
||||
name: X-API-Key
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- active: "1"
|
||||
attributes:
|
||||
force_pw_update: "0"
|
||||
mailbox_format: "maildir:"
|
||||
quarantine_notification: never
|
||||
sogo_access: "1"
|
||||
tls_enforce_in: "0"
|
||||
tls_enforce_out: "0"
|
||||
domain: domain3.tld
|
||||
is_relayed: 0
|
||||
local_part: info
|
||||
max_new_quota: 10737418240
|
||||
messages: 0
|
||||
name: Full name
|
||||
percent_class: success
|
||||
percent_in_use: 0
|
||||
quota: 3221225472
|
||||
quota_used: 0
|
||||
rl: false
|
||||
spam_aliases: 0
|
||||
username: info@domain3.tld
|
||||
tags: ["tag1", "tag2"]
|
||||
description: OK
|
||||
headers: {}
|
||||
tags:
|
||||
- Mailboxes
|
||||
description: You can list all mailboxes existing in system for a specific domain.
|
||||
operationId: Get mailboxes of a domain
|
||||
summary: Get mailboxes of a domain
|
||||
|
||||
tags:
|
||||
- name: Domains
|
||||
|
@@ -128,10 +128,10 @@ table.footable > tbody > tr.footable-empty > th {
|
||||
content: "\f130";
|
||||
}
|
||||
.fooicon-plus:before {
|
||||
content: "\f4fc";
|
||||
content: "\f4fd";
|
||||
}
|
||||
.fooicon-minus:before {
|
||||
content: "\f2e8";
|
||||
content: "\f2e9";
|
||||
}
|
||||
.fooicon-search:before {
|
||||
content: "\f52a";
|
||||
|
2
data/web/css/build/007-languages.min.css
vendored
2
data/web/css/build/007-languages.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -127,6 +127,7 @@ elseif (!empty($_GET['id']) && ctype_alnum($_GET['id'])) {
|
||||
$data['fuzzy_hashes'] = json_decode($mailc['fuzzy_hashes']);
|
||||
// Get text/plain content
|
||||
$data['text_plain'] = $mail_parser->getMessageBody('text');
|
||||
if (!json_encode($data['text_plain'])) $data['text_plain'] = '';
|
||||
// Get html content and convert to text
|
||||
$data['text_html'] = $html2text->convert($mail_parser->getMessageBody('html'));
|
||||
if (empty($data['text_plain']) && empty($data['text_html'])) {
|
||||
|
@@ -51,6 +51,7 @@ function pushover($_action, $_data = null) {
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
$evaluate_x_prio = (isset($_data['evaluate_x_prio'])) ? intval($_data['evaluate_x_prio']) : $is_now['evaluate_x_prio'];
|
||||
$only_x_prio = (isset($_data['only_x_prio'])) ? intval($_data['only_x_prio']) : $is_now['only_x_prio'];
|
||||
$sound = (isset($_data['sound'])) ? $_data['sound'] : $is_now['sound'];
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -101,7 +102,8 @@ function pushover($_action, $_data = null) {
|
||||
$po_attributes = json_encode(
|
||||
array(
|
||||
'evaluate_x_prio' => strval(intval($evaluate_x_prio)),
|
||||
'only_x_prio' => strval(intval($only_x_prio))
|
||||
'only_x_prio' => strval(intval($only_x_prio)),
|
||||
'sound' => strval($sound)
|
||||
)
|
||||
);
|
||||
$stmt = $pdo->prepare("REPLACE INTO `pushover` (`username`, `key`, `attributes`, `senders_regex`, `senders`, `token`, `title`, `text`, `active`)
|
||||
|
@@ -3,7 +3,7 @@ function init_db_schema() {
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "25072022_2300";
|
||||
$db_version = "17112022_2115";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -1264,6 +1264,7 @@ function init_db_schema() {
|
||||
$pdo->query("UPDATE `pushover` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
|
||||
$pdo->query("UPDATE `pushover` SET `attributes` = JSON_SET(`attributes`, '$.evaluate_x_prio', \"0\") WHERE JSON_VALUE(`attributes`, '$.evaluate_x_prio') IS NULL;");
|
||||
$pdo->query("UPDATE `pushover` SET `attributes` = JSON_SET(`attributes`, '$.only_x_prio', \"0\") WHERE JSON_VALUE(`attributes`, '$.only_x_prio') IS NULL;");
|
||||
$pdo->query("UPDATE `pushover` SET `attributes` = JSON_SET(`attributes`, '$.sound', \"pushover\") WHERE JSON_VALUE(`attributes`, '$.sound') IS NULL;");
|
||||
// mailbox
|
||||
$pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
|
||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.passwd_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.passwd_update') IS NULL;");
|
||||
|
16
data/web/inc/lib/composer.lock
generated
16
data/web/inc/lib/composer.lock
generated
@@ -1604,16 +1604,16 @@
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.3.8",
|
||||
"version": "v3.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c"
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1628,7 +1628,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1664,7 +1664,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.3.8"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1676,7 +1676,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-02-04T06:59:48+00:00"
|
||||
"time": "2022-09-28T08:42:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yubico/u2flib-server",
|
||||
@@ -1728,5 +1728,5 @@
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.2.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
5
data/web/inc/lib/vendor/autoload.php
vendored
5
data/web/inc/lib/vendor/autoload.php
vendored
@@ -2,6 +2,11 @@
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b::getLoader();
|
||||
|
@@ -21,12 +21,14 @@ use Composer\Semver\VersionParser;
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
@@ -37,7 +39,7 @@ class InstalledVersions
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
@@ -241,7 +243,7 @@ class InstalledVersions
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
@@ -255,7 +257,7 @@ class InstalledVersions
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@@ -278,7 +280,7 @@ class InstalledVersions
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
@@ -301,7 +303,7 @@ class InstalledVersions
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
@@ -311,7 +313,7 @@ class InstalledVersions
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@@ -2,15 +2,15 @@
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
|
||||
'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
|
||||
'04c6c5c2f7095ccf6c481d3e53e1776f' => $vendorDir . '/mustangostang/spyc/Spyc.php',
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@@ -25,38 +25,15 @@ class ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit873464e4bd965a3168f133248b1b218b::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit873464e4bd965a3168f133248b1b218b::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit873464e4bd965a3168f133248b1b218b::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit873464e4bd965a3168f133248b1b218b::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire873464e4bd965a3168f133248b1b218b($fileIdentifier, $file);
|
||||
}
|
||||
|
@@ -8,10 +8,10 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
{
|
||||
public static $files = array (
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
|
||||
'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
|
||||
'04c6c5c2f7095ccf6c481d3e53e1776f' => __DIR__ . '/..' . '/mustangostang/spyc/Spyc.php',
|
||||
|
16
data/web/inc/lib/vendor/composer/installed.json
vendored
16
data/web/inc/lib/vendor/composer/installed.json
vendored
@@ -1654,17 +1654,17 @@
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.3.8",
|
||||
"version_normalized": "3.3.8.0",
|
||||
"version": "v3.4.3",
|
||||
"version_normalized": "3.4.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c"
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1676,11 +1676,11 @@
|
||||
"psr/container": "^1.0",
|
||||
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
|
||||
},
|
||||
"time": "2022-02-04T06:59:48+00:00",
|
||||
"time": "2022-09-28T08:42:51+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
@@ -1717,7 +1717,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.3.8"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
68
data/web/inc/lib/vendor/composer/installed.php
vendored
68
data/web/inc/lib/vendor/composer/installed.php
vendored
@@ -1,49 +1,49 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '8e0b1d8aee4af02311692cb031695cc2ac3850fd',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => NULL,
|
||||
'name' => '__root__',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '8e0b1d8aee4af02311692cb031695cc2ac3850fd',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => NULL,
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'bshaffer/oauth2-server-php' => array(
|
||||
'pretty_version' => 'v1.11.1',
|
||||
'version' => '1.11.1.0',
|
||||
'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
|
||||
'aliases' => array(),
|
||||
'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ddeboer/imap' => array(
|
||||
'pretty_version' => '1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
'reference' => '8b772d04b1deadb5df13782fb78c4b648f77496e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ddeboer/imap',
|
||||
'aliases' => array(),
|
||||
'reference' => '8b772d04b1deadb5df13782fb78c4b648f77496e',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'directorytree/ldaprecord' => array(
|
||||
'pretty_version' => 'v2.10.1',
|
||||
'version' => '2.10.1.0',
|
||||
'reference' => 'bf512d9af7a7b0e2ed7a666ab29cefdd027bee88',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../directorytree/ldaprecord',
|
||||
'aliases' => array(),
|
||||
'reference' => 'bf512d9af7a7b0e2ed7a666ab29cefdd027bee88',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'exorus/php-mime-mail-parser' => array(
|
||||
@@ -55,28 +55,28 @@
|
||||
'illuminate/contracts' => array(
|
||||
'pretty_version' => 'v9.3.0',
|
||||
'version' => '9.3.0.0',
|
||||
'reference' => 'bf4b3c254c49d28157645d01e4883b5951b1e1d0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/contracts',
|
||||
'aliases' => array(),
|
||||
'reference' => 'bf4b3c254c49d28157645d01e4883b5951b1e1d0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'matthiasmullie/minify' => array(
|
||||
'pretty_version' => '1.3.66',
|
||||
'version' => '1.3.66.0',
|
||||
'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../matthiasmullie/minify',
|
||||
'aliases' => array(),
|
||||
'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'matthiasmullie/path-converter' => array(
|
||||
'pretty_version' => '1.1.3',
|
||||
'version' => '1.1.3.0',
|
||||
'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../matthiasmullie/path-converter',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'messaged/php-mime-mail-parser' => array(
|
||||
@@ -88,136 +88,136 @@
|
||||
'mustangostang/spyc' => array(
|
||||
'pretty_version' => '0.6.3',
|
||||
'version' => '0.6.3.0',
|
||||
'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../mustangostang/spyc',
|
||||
'aliases' => array(),
|
||||
'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nesbot/carbon' => array(
|
||||
'pretty_version' => '2.57.0',
|
||||
'version' => '2.57.0.0',
|
||||
'reference' => '4a54375c21eea4811dbd1149fe6b246517554e78',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nesbot/carbon',
|
||||
'aliases' => array(),
|
||||
'reference' => '4a54375c21eea4811dbd1149fe6b246517554e78',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'paragonie/random_compat' => array(
|
||||
'pretty_version' => 'v9.99.100',
|
||||
'version' => '9.99.100.0',
|
||||
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||
'aliases' => array(),
|
||||
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-mime-mail-parser/php-mime-mail-parser' => array(
|
||||
'pretty_version' => '7.0.0',
|
||||
'version' => '7.0.0.0',
|
||||
'reference' => '9d09a017f3f103fec8456211a4a538b80e0eca0d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-mime-mail-parser/php-mime-mail-parser',
|
||||
'aliases' => array(),
|
||||
'reference' => '9d09a017f3f103fec8456211a4a538b80e0eca0d',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
'pretty_version' => 'v6.6.0',
|
||||
'version' => '6.6.0.0',
|
||||
'reference' => 'e43bac82edc26ca04b36143a48bde1c051cfd5b1',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e43bac82edc26ca04b36143a48bde1c051cfd5b1',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => '8707bf3cea6f710bf6ef05491234e3ab06f6432a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||
'aliases' => array(),
|
||||
'reference' => '8707bf3cea6f710bf6ef05491234e3ab06f6432a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'robthree/twofactorauth' => array(
|
||||
'pretty_version' => '1.8.1',
|
||||
'version' => '1.8.1.0',
|
||||
'reference' => '5afcb45282f1c75562a48d479ecd1732c9bdb11b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../robthree/twofactorauth',
|
||||
'aliases' => array(),
|
||||
'reference' => '5afcb45282f1c75562a48d479ecd1732c9bdb11b',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'soundasleep/html2text' => array(
|
||||
'pretty_version' => '0.5.0',
|
||||
'version' => '0.5.0.0',
|
||||
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../soundasleep/html2text',
|
||||
'aliases' => array(),
|
||||
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-ctype' => array(
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'reference' => '30885182c981ab175d4d034db0f6f469898070ab',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
||||
'aliases' => array(),
|
||||
'reference' => '30885182c981ab175d4d034db0f6f469898070ab',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation' => array(
|
||||
'pretty_version' => 'v6.0.5',
|
||||
'version' => '6.0.5.0',
|
||||
'reference' => 'e69501c71107cc3146b32aaa45f4edd0c3427875',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e69501c71107cc3146b32aaa45f4edd0c3427875',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation-contracts' => array(
|
||||
'pretty_version' => 'v3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '1b6ea5a7442af5a12dba3dbd6d71034b5b234e77',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation-contracts',
|
||||
'aliases' => array(),
|
||||
'reference' => '1b6ea5a7442af5a12dba3dbd6d71034b5b234e77',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation-implementation' => array(
|
||||
@@ -229,37 +229,37 @@
|
||||
'symfony/var-dumper' => array(
|
||||
'pretty_version' => 'v6.0.5',
|
||||
'version' => '6.0.5.0',
|
||||
'reference' => '60d6a756d5f485df5e6e40b337334848f79f61ce',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||
'aliases' => array(),
|
||||
'reference' => '60d6a756d5f485df5e6e40b337334848f79f61ce',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tightenco/collect' => array(
|
||||
'pretty_version' => 'v8.83.2',
|
||||
'version' => '8.83.2.0',
|
||||
'reference' => 'd9c66d586ec2d216d8a31283d73f8df1400cc722',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../tightenco/collect',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd9c66d586ec2d216d8a31283d73f8df1400cc722',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'twig/twig' => array(
|
||||
'pretty_version' => 'v3.3.8',
|
||||
'version' => '3.3.8.0',
|
||||
'pretty_version' => 'v3.4.3',
|
||||
'version' => '3.4.3.0',
|
||||
'reference' => 'c38fd6b0b7f370c198db91ffd02e23b517426b58',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../twig/twig',
|
||||
'aliases' => array(),
|
||||
'reference' => '972d8604a92b7054828b539f2febb0211dd5945c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yubico/u2flib-server' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'reference' => '55d813acf68212ad2cadecde07551600d6971939',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../yubico/u2flib-server',
|
||||
'aliases' => array(),
|
||||
'reference' => '55d813acf68212ad2cadecde07551600d6971939',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/doc/** export-ignore
|
||||
/extra/** export-ignore
|
||||
/tests export-ignore
|
||||
/doc/ export-ignore
|
||||
/extra/ export-ignore
|
||||
/tests/ export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
|
@@ -9,6 +9,9 @@ on:
|
||||
env:
|
||||
SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: 1
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: "PHP ${{ matrix.php-version }}"
|
||||
@@ -25,36 +28,23 @@ jobs:
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
composer-options: ['']
|
||||
experimental: [false]
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2.3.3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Install PHP with extensions"
|
||||
uses: shivammathur/setup-php@2.7.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: ${{ matrix.php-version }}
|
||||
ini-values: memory_limit=-1
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Add PHPUnit matcher"
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: "Set composer cache directory"
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: "Cache composer"
|
||||
uses: actions/cache@v2.1.2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-composer-
|
||||
|
||||
- run: composer install ${{ matrix.composer-options }}
|
||||
- run: composer install
|
||||
|
||||
- name: "Install PHPUnit"
|
||||
run: vendor/bin/simple-phpunit install
|
||||
@@ -92,35 +82,22 @@ jobs:
|
||||
- 'extra/markdown-extra'
|
||||
- 'extra/string-extra'
|
||||
- 'extra/twig-extra-bundle'
|
||||
composer-options: ['']
|
||||
experimental: [false]
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2.3.3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Install PHP with extensions"
|
||||
uses: shivammathur/setup-php@2.7.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: ${{ matrix.php-version }}
|
||||
ini-values: memory_limit=-1
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Add PHPUnit matcher"
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: "Set composer cache directory"
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: "Cache composer"
|
||||
uses: actions/cache@v2.1.2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-${{ hashFiles('composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-
|
||||
|
||||
- run: composer install
|
||||
|
||||
- name: "Install PHPUnit"
|
||||
@@ -129,10 +106,6 @@ jobs:
|
||||
- name: "PHPUnit version"
|
||||
run: vendor/bin/simple-phpunit --version
|
||||
|
||||
- if: matrix.extension == 'extra/markdown-extra' && matrix.php-version == '8.0'
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: composer config platform.php 7.4.99
|
||||
|
||||
- name: "Composer install"
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: composer install
|
||||
@@ -140,6 +113,7 @@ jobs:
|
||||
- name: "Run tests"
|
||||
working-directory: ${{ matrix.extension}}
|
||||
run: ../../vendor/bin/simple-phpunit
|
||||
|
||||
#
|
||||
# Drupal does not support Twig 3 now!
|
||||
#
|
||||
@@ -160,10 +134,10 @@ jobs:
|
||||
#
|
||||
# steps:
|
||||
# - name: "Checkout code"
|
||||
# uses: actions/checkout@v2.3.3
|
||||
# uses: actions/checkout@v2
|
||||
#
|
||||
# - name: "Install PHP with extensions"
|
||||
# uses: shivammathur/setup-php@2.7.0
|
||||
# uses: shivammathur/setup-php@2
|
||||
# with:
|
||||
# coverage: "none"
|
||||
# extensions: "gd, pdo_sqlite"
|
||||
|
@@ -4,8 +4,12 @@ on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '2.x'
|
||||
- '3.x'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build"
|
||||
@@ -16,32 +20,32 @@ jobs:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Set up Python 3.7"
|
||||
uses: actions/setup-python@v1
|
||||
- name: "Set-up PHP"
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
python-version: '3.7' # Semantic version range syntax or exact version of a Python version
|
||||
php-version: 8.1
|
||||
coverage: none
|
||||
tools: "composer:v2"
|
||||
|
||||
- name: "Display Python version"
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
- name: Get composer cache directory
|
||||
id: composercache
|
||||
working-directory: doc/_build
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: "Install Sphinx dependencies"
|
||||
run: sudo apt-get install python-dev build-essential
|
||||
|
||||
- name: "Cache pip"
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('_build/.requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
path: ${{ steps.composercache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: "Install Sphinx + requirements via pip"
|
||||
working-directory: "doc"
|
||||
run: pip install -r _build/.requirements.txt
|
||||
- name: "Install dependencies"
|
||||
working-directory: doc/_build
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
- name: "Build documentation"
|
||||
working-directory: "doc"
|
||||
run: make -C _build SPHINXOPTS="-nqW -j auto" html
|
||||
- name: "Build the docs"
|
||||
working-directory: doc/_build
|
||||
run: php build.php --disable-cache
|
||||
|
||||
doctor-rst:
|
||||
name: "DOCtor-RST"
|
||||
|
2
data/web/inc/lib/vendor/twig/twig/.gitignore
vendored
2
data/web/inc/lib/vendor/twig/twig/.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
/doc/_build/vendor
|
||||
/doc/_build/output
|
||||
/composer.lock
|
||||
/phpunit.xml
|
||||
/vendor
|
||||
|
30
data/web/inc/lib/vendor/twig/twig/CHANGELOG
vendored
30
data/web/inc/lib/vendor/twig/twig/CHANGELOG
vendored
@@ -1,6 +1,36 @@
|
||||
# 3.4.3 (2022-09-28)
|
||||
|
||||
* Fix a security issue on filesystem loader (possibility to load a template outside a configured directory)
|
||||
|
||||
# 3.4.2 (2022-08-12)
|
||||
|
||||
* Allow inherited magic method to still run with calling class
|
||||
* Fix CallExpression::reflectCallable() throwing TypeError
|
||||
* Fix typo in naming (currency_code)
|
||||
|
||||
# 3.4.1 (2022-05-17)
|
||||
|
||||
* Fix optimizing non-public named closures
|
||||
|
||||
# 3.4.0 (2022-05-22)
|
||||
|
||||
* Add support for named closures
|
||||
|
||||
# 3.3.10 (2022-04-06)
|
||||
|
||||
* Enable bytecode invalidation when auto_reload is enabled
|
||||
|
||||
# 3.3.9 (2022-03-25)
|
||||
|
||||
* Fix custom escapers when using multiple Twig environments
|
||||
* Add support for "constant('class', object)"
|
||||
* Do not reuse internally generated variable names during parsing
|
||||
|
||||
# 3.3.8 (2022-02-04)
|
||||
|
||||
* Fix a security issue when in a sandbox: the `sort` filter must require a Closure for the `arrow` parameter
|
||||
* Fix deprecation notice on `round`
|
||||
* Fix call to deprecated `convertToHtml` method
|
||||
|
||||
# 3.3.7 (2022-01-03)
|
||||
|
||||
|
@@ -44,7 +44,7 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,11 +38,11 @@ use Twig\TokenParser\TokenParserInterface;
|
||||
*/
|
||||
class Environment
|
||||
{
|
||||
public const VERSION = '3.3.8';
|
||||
public const VERSION_ID = 30308;
|
||||
public const VERSION = '3.4.3';
|
||||
public const VERSION_ID = 30403;
|
||||
public const MAJOR_VERSION = 3;
|
||||
public const MINOR_VERSION = 3;
|
||||
public const RELEASE_VERSION = 8;
|
||||
public const MINOR_VERSION = 4;
|
||||
public const RELEASE_VERSION = 3;
|
||||
public const EXTRA_VERSION = '';
|
||||
|
||||
private $charset;
|
||||
@@ -228,7 +228,7 @@ class Environment
|
||||
{
|
||||
if (\is_string($cache)) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new FilesystemCache($cache);
|
||||
$this->cache = new FilesystemCache($cache, $this->autoReload ? FilesystemCache::FORCE_BYTECODE_INVALIDATION : 0);
|
||||
} elseif (false === $cache) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new NullCache();
|
||||
|
@@ -485,7 +485,7 @@ class ExpressionParser
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext());
|
||||
throw new SyntaxError(sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext());
|
||||
}
|
||||
|
||||
if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
||||
|
@@ -1359,6 +1359,10 @@ function twig_source(Environment $env, $name, $ignoreMissing = false)
|
||||
function twig_constant($constant, $object = null)
|
||||
{
|
||||
if (null !== $object) {
|
||||
if ('class' === $constant) {
|
||||
return \get_class($object);
|
||||
}
|
||||
|
||||
$constant = \get_class($object).'::'.$constant;
|
||||
}
|
||||
|
||||
@@ -1376,6 +1380,10 @@ function twig_constant($constant, $object = null)
|
||||
function twig_constant_is_defined($constant, $object = null)
|
||||
{
|
||||
if (null !== $object) {
|
||||
if ('class' === $constant) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$constant = \get_class($object).'::'.$constant;
|
||||
}
|
||||
|
||||
|
@@ -387,13 +387,8 @@ function twig_escape_filter(Environment $env, $string, $strategy = 'html', $char
|
||||
return rawurlencode($string);
|
||||
|
||||
default:
|
||||
static $escapers;
|
||||
|
||||
if (null === $escapers) {
|
||||
$escapers = $env->getExtension(EscaperExtension::class)->getEscapers();
|
||||
}
|
||||
|
||||
if (isset($escapers[$strategy])) {
|
||||
$escapers = $env->getExtension(EscaperExtension::class)->getEscapers();
|
||||
if (array_key_exists($strategy, $escapers)) {
|
||||
return $escapers[$strategy]($env, $string, $charset);
|
||||
}
|
||||
|
||||
|
@@ -91,11 +91,11 @@ final class SandboxExtension extends AbstractExtension
|
||||
}
|
||||
}
|
||||
|
||||
public function checkPropertyAllowed($obj, $method, int $lineno = -1, Source $source = null): void
|
||||
public function checkPropertyAllowed($obj, $property, int $lineno = -1, Source $source = null): void
|
||||
{
|
||||
if ($this->isSandboxed()) {
|
||||
try {
|
||||
$this->policy->checkPropertyAllowed($obj, $method);
|
||||
$this->policy->checkPropertyAllowed($obj, $property);
|
||||
} catch (SecurityNotAllowedPropertyError $e) {
|
||||
$e->setSourceContext($source);
|
||||
$e->setTemplateLine($lineno);
|
||||
|
@@ -183,9 +183,9 @@ class FilesystemLoader implements LoaderInterface
|
||||
}
|
||||
|
||||
try {
|
||||
$this->validateName($name);
|
||||
|
||||
list($namespace, $shortname) = $this->parseName($name);
|
||||
|
||||
$this->validateName($shortname);
|
||||
} catch (LoaderError $e) {
|
||||
if (!$throw) {
|
||||
return null;
|
||||
|
@@ -24,19 +24,20 @@ abstract class CallExpression extends AbstractExpression
|
||||
{
|
||||
$callable = $this->getAttribute('callable');
|
||||
|
||||
$closingParenthesis = false;
|
||||
$isArray = false;
|
||||
if (\is_string($callable) && false === strpos($callable, '::')) {
|
||||
$compiler->raw($callable);
|
||||
} else {
|
||||
list($r, $callable) = $this->reflectCallable($callable);
|
||||
if ($r instanceof \ReflectionMethod && \is_string($callable[0])) {
|
||||
if ($r->isStatic()) {
|
||||
[$r, $callable] = $this->reflectCallable($callable);
|
||||
|
||||
if (\is_string($callable)) {
|
||||
$compiler->raw($callable);
|
||||
} elseif (\is_array($callable) && \is_string($callable[0])) {
|
||||
if (!$r instanceof \ReflectionMethod || $r->isStatic()) {
|
||||
$compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
|
||||
} else {
|
||||
$compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
|
||||
}
|
||||
} elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof ExtensionInterface) {
|
||||
} elseif (\is_array($callable) && $callable[0] instanceof ExtensionInterface) {
|
||||
$class = \get_class($callable[0]);
|
||||
if (!$compiler->getEnvironment()->hasExtension($class)) {
|
||||
// Compile a non-optimized call to trigger a \Twig\Error\RuntimeError, which cannot be a compile-time error
|
||||
@@ -47,17 +48,11 @@ abstract class CallExpression extends AbstractExpression
|
||||
|
||||
$compiler->raw(sprintf('->%s', $callable[1]));
|
||||
} else {
|
||||
$closingParenthesis = true;
|
||||
$isArray = true;
|
||||
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', ucfirst($this->getAttribute('type')), $this->getAttribute('name')));
|
||||
$compiler->raw(sprintf('$this->env->get%s(\'%s\')->getCallable()', ucfirst($this->getAttribute('type')), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
|
||||
$this->compileArguments($compiler, $isArray);
|
||||
|
||||
if ($closingParenthesis) {
|
||||
$compiler->raw(')');
|
||||
}
|
||||
$this->compileArguments($compiler);
|
||||
}
|
||||
|
||||
protected function compileArguments(Compiler $compiler, $isArray = false): void
|
||||
@@ -244,10 +239,7 @@ abstract class CallExpression extends AbstractExpression
|
||||
|
||||
private function getCallableParameters($callable, bool $isVariadic): array
|
||||
{
|
||||
list($r) = $this->reflectCallable($callable);
|
||||
if (null === $r) {
|
||||
return [[], false];
|
||||
}
|
||||
[$r, , $callableName] = $this->reflectCallable($callable);
|
||||
|
||||
$parameters = $r->getParameters();
|
||||
if ($this->hasNode('node')) {
|
||||
@@ -274,11 +266,6 @@ abstract class CallExpression extends AbstractExpression
|
||||
array_pop($parameters);
|
||||
$isPhpVariadic = true;
|
||||
} else {
|
||||
$callableName = $r->name;
|
||||
if ($r instanceof \ReflectionMethod) {
|
||||
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
||||
}
|
||||
|
||||
throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
@@ -292,29 +279,41 @@ abstract class CallExpression extends AbstractExpression
|
||||
return $this->reflector;
|
||||
}
|
||||
|
||||
if (\is_array($callable)) {
|
||||
if (!method_exists($callable[0], $callable[1])) {
|
||||
// __call()
|
||||
return [null, []];
|
||||
}
|
||||
$r = new \ReflectionMethod($callable[0], $callable[1]);
|
||||
} elseif (\is_object($callable) && !$callable instanceof \Closure) {
|
||||
$r = new \ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
$callable = [$callable, '__invoke'];
|
||||
} elseif (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
||||
$class = substr($callable, 0, $pos);
|
||||
$method = substr($callable, $pos + 2);
|
||||
if (!method_exists($class, $method)) {
|
||||
// __staticCall()
|
||||
return [null, []];
|
||||
}
|
||||
$r = new \ReflectionMethod($callable);
|
||||
$callable = [$class, $method];
|
||||
} else {
|
||||
$r = new \ReflectionFunction($callable);
|
||||
if (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
||||
$callable = [substr($callable, 0, $pos), substr($callable, 2 + $pos)];
|
||||
}
|
||||
|
||||
return $this->reflector = [$r, $callable];
|
||||
if (\is_array($callable) && method_exists($callable[0], $callable[1])) {
|
||||
$r = new \ReflectionMethod($callable[0], $callable[1]);
|
||||
|
||||
return $this->reflector = [$r, $callable, $r->class.'::'.$r->name];
|
||||
}
|
||||
|
||||
$checkVisibility = $callable instanceof \Closure;
|
||||
try {
|
||||
$closure = \Closure::fromCallable($callable);
|
||||
} catch (\TypeError $e) {
|
||||
throw new \LogicException(sprintf('Callback for %s "%s" is not callable in the current scope.', $this->getAttribute('type'), $this->getAttribute('name')), 0, $e);
|
||||
}
|
||||
$r = new \ReflectionFunction($closure);
|
||||
|
||||
if (false !== strpos($r->name, '{closure}')) {
|
||||
return $this->reflector = [$r, $callable, 'Closure'];
|
||||
}
|
||||
|
||||
if ($object = $r->getClosureThis()) {
|
||||
$callable = [$object, $r->name];
|
||||
$callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name;
|
||||
} elseif ($class = $r->getClosureScopeClass()) {
|
||||
$callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
|
||||
} else {
|
||||
$callable = $callableName = $r->name;
|
||||
}
|
||||
|
||||
if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) {
|
||||
$callable = $r->getClosure();
|
||||
}
|
||||
|
||||
return $this->reflector = [$r, $callable, $callableName];
|
||||
}
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ class Parser
|
||||
public function parse(TokenStream $stream, $test = null, bool $dropNeedle = false): ModuleNode
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames'], $vars['varNameSalt']);
|
||||
$this->stack[] = $vars;
|
||||
|
||||
// node visitors
|
||||
@@ -78,7 +78,6 @@ class Parser
|
||||
$this->blockStack = [];
|
||||
$this->importedSymbols = [[]];
|
||||
$this->embeddedTemplates = [];
|
||||
$this->varNameSalt = 0;
|
||||
|
||||
try {
|
||||
$body = $this->subparse($test, $dropNeedle);
|
||||
|
@@ -19,17 +19,27 @@ namespace Twig\Sandbox;
|
||||
interface SecurityPolicyInterface
|
||||
{
|
||||
/**
|
||||
* @param string[] $tags
|
||||
* @param string[] $filters
|
||||
* @param string[] $functions
|
||||
*
|
||||
* @throws SecurityError
|
||||
*/
|
||||
public function checkSecurity($tags, $filters, $functions): void;
|
||||
|
||||
/**
|
||||
* @param object $obj
|
||||
* @param string $method
|
||||
*
|
||||
* @throws SecurityNotAllowedMethodError
|
||||
*/
|
||||
public function checkMethodAllowed($obj, $method): void;
|
||||
|
||||
/**
|
||||
* @param object $obj
|
||||
* @param string $property
|
||||
*
|
||||
* @throws SecurityNotAllowedPropertyError
|
||||
*/
|
||||
public function checkPropertyAllowed($obj, $method): void;
|
||||
public function checkPropertyAllowed($obj, $property): void;
|
||||
}
|
||||
|
@@ -195,9 +195,65 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
|
||||
// Set language
|
||||
if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) {
|
||||
if ($DETECT_LANGUAGE && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
$header_lang = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
|
||||
if (array_key_exists($header_lang, $AVAILABLE_LANGUAGES)) {
|
||||
$_SESSION['mailcow_locale'] = $header_lang;
|
||||
// regex inspired from @GabrielAnderson on http://stackoverflow.com/questions/6038236/http-accept-language
|
||||
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})*)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
|
||||
|
||||
$langs = $lang_parse[1];
|
||||
$ranks = $lang_parse[4];
|
||||
|
||||
// (create an associative array 'language' => 'preference')
|
||||
$lang2pref = array();
|
||||
for ($i=0; $i<count($langs); $i++) {
|
||||
$lang2pref[strtolower($langs[$i])] = (float) (!empty($ranks[$i]) ? $ranks[$i] : 1);
|
||||
}
|
||||
|
||||
// (comparison function for uksort)
|
||||
$cmpLangs = function ($a, $b) use ($lang2pref) {
|
||||
if ($lang2pref[$a] > $lang2pref[$b])
|
||||
return -1;
|
||||
elseif ($lang2pref[$a] < $lang2pref[$b])
|
||||
return 1;
|
||||
elseif (strlen($a) > strlen($b))
|
||||
return -1;
|
||||
elseif (strlen($a) < strlen($b))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
|
||||
// sort the languages by prefered language and by the most specific region
|
||||
uksort($lang2pref, $cmpLangs);
|
||||
|
||||
// generate language array without the region part
|
||||
$AVAILABLE_BASE_LANGUAGES=array();
|
||||
foreach ($AVAILABLE_LANGUAGES as $code => $lang) {
|
||||
$base_code = substr($code, 0, 2);
|
||||
if (!array_key_exists($base_code, $AVAILABLE_BASE_LANGUAGES)) {
|
||||
$AVAILABLE_BASE_LANGUAGES[$base_code] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a perfect match or partial match
|
||||
// Match en-gb or en
|
||||
foreach ($lang2pref as $lang => $q) {
|
||||
if (array_key_exists($lang, $AVAILABLE_LANGUAGES)) {
|
||||
$_SESSION['mailcow_locale'] = $lang;
|
||||
break;
|
||||
} elseif (array_key_exists($lang, $AVAILABLE_BASE_LANGUAGES)) {
|
||||
$_SESSION['mailcow_locale'] = $AVAILABLE_BASE_LANGUAGES[$lang];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try suggest match
|
||||
// e.g. suggest en-gb when only en-us is provided
|
||||
if (!isset($_COOKIE['mailcow_locale'])) {
|
||||
foreach ($lang2pref as $lang => $q) {
|
||||
if (array_key_exists(substr($lang, 0, 2), $AVAILABLE_BASE_LANGUAGES)) {
|
||||
$_SESSION['mailcow_locale'] = $AVAILABLE_BASE_LANGUAGES[substr($lang, 0, 2)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -215,7 +271,7 @@ if (isset($_GET['lang']) && array_key_exists($_GET['lang'], $AVAILABLE_LANGUAGES
|
||||
/*
|
||||
* load language
|
||||
*/
|
||||
$lang = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.json'), true);
|
||||
$lang = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en-gb.json'), true);
|
||||
|
||||
$langFile = $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.json';
|
||||
if(file_exists($langFile)) {
|
||||
|
@@ -76,33 +76,35 @@ $autodiscover_config = array(
|
||||
$DETECT_LANGUAGE = true;
|
||||
|
||||
// Change default language
|
||||
$DEFAULT_LANG = 'en';
|
||||
$DEFAULT_LANG = 'en-gb';
|
||||
|
||||
// Available languages
|
||||
// https://www.iso.org/obp/ui/#search
|
||||
// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||
// https://en.wikipedia.org/wiki/IETF_language_tag
|
||||
$AVAILABLE_LANGUAGES = array(
|
||||
'cs' => 'Čeština (Czech)',
|
||||
'da' => 'Danish (Dansk)',
|
||||
'de' => 'Deutsch (German)',
|
||||
'en' => 'English',
|
||||
'es' => 'Español (Spanish)',
|
||||
'fi' => 'Suomi (Finish)',
|
||||
'fr' => 'Français (French)',
|
||||
'hu' => 'Magyar (Hungarian)',
|
||||
'it' => 'Italiano (Italian)',
|
||||
'ko' => '한국어 (Korean)',
|
||||
'lv' => 'latviešu (Latvian)',
|
||||
'nl' => 'Nederlands (Dutch)',
|
||||
'pl' => 'Język Polski (Polish)',
|
||||
'pt' => 'Português (Portuguese)',
|
||||
'ro' => 'Română (Romanian)',
|
||||
'ru' => 'Pусский (Russian)',
|
||||
'sk' => 'Slovenčina (Slovak)',
|
||||
'sv' => 'Svenska (Swedish)',
|
||||
'tr' => 'Türkçe (Turkish)',
|
||||
'uk' => 'Українська (Ukrainian)',
|
||||
'zh' => '中文 (Chinese)'
|
||||
// 'ca-es' => 'Català (Catalan)',
|
||||
'cs-cz' => 'Čeština (Czech)',
|
||||
'da-dk' => 'Danish (Dansk)',
|
||||
'de-de' => 'Deutsch (German)',
|
||||
'en-gb' => 'English',
|
||||
'es-es' => 'Español (Spanish)',
|
||||
'fi-fi' => 'Suomi (Finish)',
|
||||
'fr-fr' => 'Français (French)',
|
||||
'hu-hu' => 'Magyar (Hungarian)',
|
||||
'it-it' => 'Italiano (Italian)',
|
||||
'ko-kr' => '한국어 (Korean)',
|
||||
'lv-lv' => 'latviešu (Latvian)',
|
||||
'nl-nl' => 'Nederlands (Dutch)',
|
||||
'pl-pl' => 'Język Polski (Polish)',
|
||||
'pt-pt' => 'Português (Portuguese)',
|
||||
'ro-ro' => 'Română (Romanian)',
|
||||
'ru-ru' => 'Pусский (Russian)',
|
||||
'sk-sk' => 'Slovenčina (Slovak)',
|
||||
'sv-se' => 'Svenska (Swedish)',
|
||||
'tr-tr' => 'Türkçe (Turkish)',
|
||||
'uk-ua' => 'Українська (Ukrainian)',
|
||||
'zh-cn' => '简体中文 (Simplified Chinese)',
|
||||
'zh-tw' => '繁體中文 (Traditional Chinese)',
|
||||
);
|
||||
|
||||
// Change theme (default: lumen)
|
||||
|
@@ -265,8 +265,8 @@
|
||||
"quota_notification_html": "Benachrichtigungs-E-Mail Inhalt:<br><small>Leer lassen, um Standard-Template wiederherzustellen.</small>",
|
||||
"quota_notification_sender": "Benachrichtigungs-E-Mail Absender",
|
||||
"quota_notification_subject": "Benachrichtigungs-E-Mail Betreff",
|
||||
"quota_notifications": "Quota Benachrichtigungen",
|
||||
"quota_notifications_info": "Quota Benachrichtigungen werden an Mailboxen versendet, die 80 respektive 95 Prozent der zur Verfügung stehenden Quota überschreiten.",
|
||||
"quota_notifications": "Quota-Benachrichtigungen",
|
||||
"quota_notifications_info": "Quota-Benachrichtigungen werden an Mailboxen versendet, die 80 respektive 95 Prozent der zur Verfügung stehenden Quota überschreiten.",
|
||||
"quota_notifications_vars": "{{percent}} entspricht der aktuellen Quota in Prozent<br>{{username}} entspricht dem Mailbox-Namen",
|
||||
"r_active": "Aktive Restriktionen",
|
||||
"r_inactive": "Inaktive Restriktionen",
|
@@ -574,6 +574,7 @@
|
||||
"pushover_sender_regex": "Consider the following sender regex",
|
||||
"pushover_text": "Notification text",
|
||||
"pushover_title": "Notification title",
|
||||
"pushover_sound": "Sound",
|
||||
"pushover_vars": "When no sender filter is defined, all mails will be considered.<br>Regex filters as well as exact sender checks can be defined individually and will be considered sequentially. They do not depend on each other.<br>Useable variables for text and title (please take note of data protection policies)",
|
||||
"pushover_verify": "Verify credentials",
|
||||
"quota_mb": "Quota (MiB)",
|
||||
@@ -1097,6 +1098,7 @@
|
||||
"pushover_sender_regex": "Match senders by the following regex",
|
||||
"pushover_text": "Notification text",
|
||||
"pushover_title": "Notification title",
|
||||
"pushover_sound": "Sound",
|
||||
"pushover_vars": "When no sender filter is defined, all mails will be considered.<br>Regex filters as well as exact sender checks can be defined individually and will be considered sequentially. They do not depend on each other.<br>Useable variables for text and title (please take note of data protection policies)",
|
||||
"pushover_verify": "Verify credentials",
|
||||
"q_add_header": "Junk folder",
|
@@ -536,6 +536,7 @@
|
||||
"pushover_sender_regex": "Uitsluitend een afzender met de volgende regex",
|
||||
"pushover_text": "Meldingstekst ({SUBJECT} zal worden vervangen door het onderwerp)",
|
||||
"pushover_title": "Meldingstitel",
|
||||
"pushover_sound": "Geluid",
|
||||
"pushover_vars": "Wanneer er geen afzenders zijn uitgesloten zullen alle mails doorkomen.<br>Regex-filters en afzendercontroles kunnen individueel worden ingesteld en zullen in volgorde worden verwerkt. Ze zijn niet afhankelijk van elkaar.<br>Bruikbare variabelen voor tekst en titel (neem het gegevensbeschermingsbeleid in acht)",
|
||||
"pushover_verify": "Verifieer aanmeldingsgegevens",
|
||||
"quota_mb": "Quota (MiB)",
|
||||
@@ -1002,6 +1003,7 @@
|
||||
"pushover_sender_regex": "Uitsluitend een afzender met de volgende regex",
|
||||
"pushover_text": "Meldingstekst ({SUBJECT} zal worden vervangen door het onderwerp)",
|
||||
"pushover_title": "Meldingstitel",
|
||||
"pushover_sound": "Geluid",
|
||||
"pushover_vars": "Wanneer er geen afzenders zijn uitgesloten zullen alle mails doorkomen.<br>Regex-filters en afzendercontroles kunnen individueel worden ingesteld en zullen in volgorde worden verwerkt. Ze zijn niet afhankelijk van elkaar.<br>Bruikbare variabelen voor tekst en titel (let op het gegevensbeschermingsbeleid)",
|
||||
"pushover_verify": "Verifieer aanmeldingsgegevens",
|
||||
"q_add_header": "Spamfolder",
|
@@ -106,7 +106,7 @@
|
||||
"username": "Používateľské meno",
|
||||
"validate": "Overiť",
|
||||
"validation_success": "Úspešne overené",
|
||||
"app_passwd_protocols": "Povolené protokoly"
|
||||
"app_passwd_protocols": "Povolené protokoly k heslu aplikácie"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Prístup",
|
1187
data/web/lang/lang.zh-cn.json
Normal file
1187
data/web/lang/lang.zh-cn.json
Normal file
File diff suppressed because it is too large
Load Diff
1187
data/web/lang/lang.zh-tw.json
Normal file
1187
data/web/lang/lang.zh-tw.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,12 +32,12 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if mailcow_locale %}
|
||||
<li class="dropdown{% if available_languages|length == 1 %}lang-link-disabled{% endif %}">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="flag-icon flag-icon-{{ mailcow_locale }}"></span><span class="caret"></span></a>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="flag-icon flag-icon-{{ mailcow_locale[-2:] }}"></span><span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
{% for key, val in available_languages %}
|
||||
<li{% if mailcow_locale == key %} class="active"{% endif %}>
|
||||
<a href="?{{ query_string({'lang': key}) }}">
|
||||
<span class="flag-icon flag-icon-{{ key }}"></span>{{ val }}
|
||||
<span class="flag-icon flag-icon-{{ key[-2:] }}"></span>{{ val }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
@@ -172,7 +172,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
||||
// TFA, CSRF, Alerts in footer.inc.php
|
||||
// Other general functions in mailcow.js
|
||||
{% for alert_type, alert_msg in alerts %}
|
||||
mailcow_alert_box('{{ alert_msg|raw }}', '{{ alert_type }}');
|
||||
mailcow_alert_box('{{ alert_msg|raw|e("js") }}', '{{ alert_type }}');
|
||||
{% endfor %}
|
||||
|
||||
// Confirm TFA modal
|
||||
|
@@ -275,7 +275,7 @@
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<p class="help-block">{{ lang.user.pushover_info|format(mailbox)|raw }}</p>
|
||||
<p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code></p>
|
||||
<p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code></p>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
@@ -308,6 +308,36 @@
|
||||
<input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label for="sound">{{ lang.edit.pushover_sound }}</label><br>
|
||||
<select name="sound" class="form-control">
|
||||
<option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
|
||||
<option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
|
||||
<option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
|
||||
<option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
|
||||
<option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
|
||||
<option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
|
||||
<option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
|
||||
<option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
|
||||
<option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
|
||||
<option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
|
||||
<option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
|
||||
<option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
|
||||
<option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
|
||||
<option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
|
||||
<option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
|
||||
<option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
|
||||
<option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
|
||||
<option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
|
||||
<option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
|
||||
<option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
|
||||
<option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
|
||||
<option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
|
||||
<option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
|
@@ -45,13 +45,13 @@
|
||||
</div>
|
||||
{% if not oauth2_request %}
|
||||
<button type="button" {% if available_languages|length == 1 %}disabled="true"{% endif %} class="btn btn-xs-lg btn-default pull-right dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="flag-icon flag-icon-{{ mailcow_locale }}"></span> <span class="caret"></span>
|
||||
<span class="flag-icon flag-icon-{{ mailcow_locale[-2:] }}"></span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu pull-right login">
|
||||
{% for key, val in available_languages %}
|
||||
<li{% if mailcow_locale == key %} class="active"{% endif %}>
|
||||
<a href="?{{ query_string({'lang': key}) }}">
|
||||
<span class="flag-icon flag-icon-{{ key }}"></span>{{ val }}
|
||||
<span class="flag-icon flag-icon-{{ key[-2:] }}"></span>{{ val }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<p class="help-block">{{ lang.user.pushover_info|format(mailcow_cc_username)|raw }}</p>
|
||||
<p class="help-block">{{ lang.user.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code></p>
|
||||
<p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code></p>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
@@ -42,6 +42,36 @@
|
||||
<input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label for="sound">{{ lang.edit.pushover_sound }}</label><br>
|
||||
<select name="sound" class="form-control">
|
||||
<option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
|
||||
<option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
|
||||
<option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
|
||||
<option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
|
||||
<option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
|
||||
<option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
|
||||
<option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
|
||||
<option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
|
||||
<option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
|
||||
<option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
|
||||
<option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
|
||||
<option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
|
||||
<option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
|
||||
<option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
|
||||
<option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
|
||||
<option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
|
||||
<option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
|
||||
<option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
|
||||
<option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
|
||||
<option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
|
||||
<option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
|
||||
<option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
|
||||
<option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.user.active }}</label>
|
||||
|
@@ -41,7 +41,7 @@ services:
|
||||
- mysql
|
||||
|
||||
redis-mailcow:
|
||||
image: redis:6-alpine
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- redis-vol-1:/data/
|
||||
restart: always
|
||||
@@ -76,7 +76,7 @@ services:
|
||||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: mailcow/rspamd:1.90
|
||||
image: mailcow/rspamd:1.91
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
@@ -106,7 +106,7 @@ services:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.79
|
||||
image: mailcow/phpfpm:1.80
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
- redis-mailcow
|
||||
@@ -168,7 +168,7 @@ services:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:1.111
|
||||
image: mailcow/sogo:1.113
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@@ -215,7 +215,7 @@ services:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:1.20
|
||||
image: mailcow/dovecot:1.21
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
dns:
|
||||
@@ -424,7 +424,7 @@ services:
|
||||
- acme
|
||||
|
||||
netfilter-mailcow:
|
||||
image: mailcow/netfilter:1.48
|
||||
image: mailcow/netfilter:1.49
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
|
@@ -26,7 +26,7 @@ if(empty($targetLang)) {
|
||||
}
|
||||
|
||||
// load master lang
|
||||
$masterLang = file_get_contents(__DIR__.'/../data/web/lang/lang.en.json');
|
||||
$masterLang = file_get_contents(__DIR__.'/../data/web/lang/lang.en-gb.json');
|
||||
$masterLang = json_decode($masterLang, true);
|
||||
|
||||
// load target lang
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DEBIAN_DOCKER_IMAGE="debian:bullseye-slim"
|
||||
DEBIAN_DOCKER_IMAGE="mailcow/backup:latest"
|
||||
|
||||
if [[ ! -z ${MAILCOW_BACKUP_LOCATION} ]]; then
|
||||
BACKUP_LOCATION="${MAILCOW_BACKUP_LOCATION}"
|
||||
@@ -52,6 +52,15 @@ BACKUP_LOCATION=$(echo ${BACKUP_LOCATION} | sed 's#/$##')
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
COMPOSE_FILE=${SCRIPT_DIR}/../docker-compose.yml
|
||||
ENV_FILE=${SCRIPT_DIR}/../.env
|
||||
THREADS=$(echo ${THREADS:-1})
|
||||
|
||||
if ! [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
|
||||
echo "Thread input is not a number!"
|
||||
exit 1
|
||||
elif [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
|
||||
echo "Using ${THREADS} Thread(s) for this run."
|
||||
echo "Notice: You can set the Thread count with the THREADS Variable before you run this script."
|
||||
fi
|
||||
|
||||
if [ ! -f ${COMPOSE_FILE} ]; then
|
||||
echo "Compose file not found"
|
||||
@@ -99,32 +108,32 @@ function backup() {
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:ro,z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="gzip --rsyncable" -Pcvpf /backup/backup_vmail.tar.gz /vmail
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_vmail.tar.gz /vmail
|
||||
;;&
|
||||
crypt|all)
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:ro,z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="gzip --rsyncable" -Pcvpf /backup/backup_crypt.tar.gz /crypt
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_crypt.tar.gz /crypt
|
||||
;;&
|
||||
redis|all)
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli save
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:ro,z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="gzip --rsyncable" -Pcvpf /backup/backup_redis.tar.gz /redis
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_redis.tar.gz /redis
|
||||
;;&
|
||||
rspamd|all)
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:ro,z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="gzip --rsyncable" -Pcvpf /backup/backup_rspamd.tar.gz /rspamd
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_rspamd.tar.gz /rspamd
|
||||
;;&
|
||||
postfix|all)
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:ro,z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="gzip --rsyncable" -Pcvpf /backup/backup_postfix.tar.gz /postfix
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_postfix.tar.gz /postfix
|
||||
;;&
|
||||
mysql|all)
|
||||
SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' ${COMPOSE_FILE})
|
||||
@@ -172,7 +181,7 @@ function restore() {
|
||||
|
||||
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
||||
COMPOSE_COMMAND="docker-compose"
|
||||
|
||||
|
||||
else
|
||||
echo -e "\e[31mCan not read DOCKER_COMPOSE_VERSION variable from mailcow.conf! Is your mailcow up to date? Exiting...\e[0m"
|
||||
exit 1
|
||||
@@ -191,7 +200,7 @@ function restore() {
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar -Pxvzf /backup/backup_vmail.tar.gz
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_vmail.tar.gz
|
||||
docker start $(docker ps -aqf name=dovecot-mailcow)
|
||||
echo
|
||||
echo "In most cases it is not required to run a full resync, you can run the command printed below at any time after testing wether the restore process broke a mailbox:"
|
||||
@@ -210,7 +219,7 @@ function restore() {
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar -Pxvzf /backup/backup_redis.tar.gz
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_redis.tar.gz
|
||||
docker start $(docker ps -aqf name=redis-mailcow)
|
||||
;;
|
||||
crypt)
|
||||
@@ -218,7 +227,7 @@ function restore() {
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar -Pxvzf /backup/backup_crypt.tar.gz
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_crypt.tar.gz
|
||||
docker start $(docker ps -aqf name=dovecot-mailcow)
|
||||
;;
|
||||
rspamd)
|
||||
@@ -226,7 +235,7 @@ function restore() {
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar -Pxvzf /backup/backup_rspamd.tar.gz
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz
|
||||
docker start $(docker ps -aqf name=rspamd-mailcow)
|
||||
;;
|
||||
postfix)
|
||||
@@ -234,7 +243,7 @@ function restore() {
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar -Pxvzf /backup/backup_postfix.tar.gz
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_postfix.tar.gz
|
||||
docker start $(docker ps -aqf name=postfix-mailcow)
|
||||
;;
|
||||
mysql|mariadb)
|
||||
@@ -371,4 +380,4 @@ elif [[ ${1} == "restore" ]]; then
|
||||
done
|
||||
echo "Restoring ${FILE_SELECTION[${input_sel}]} from ${RESTORE_POINT}..."
|
||||
restore "${RESTORE_POINT}" ${FILE_SELECTION[${input_sel}]}
|
||||
fi
|
||||
fi
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
MASTER="en"
|
||||
MASTER="en-gb"
|
||||
|
||||
DIR = "#{__dir__}/.."
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
##
|
||||
## Set haproxy_trusted_networks in Dovecots extra.conf!
|
||||
#ä
|
||||
##
|
||||
|
||||
version: '2.1'
|
||||
services:
|
||||
|
@@ -50,7 +50,7 @@ echo -e "\e[32mTrying to determine GLIBC version...\e[0m"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\e[33mWARNING: $COMPOSE_PATH is not writable, but new version $LATEST_COMPOSE is available (installed: $COMPOSE_VERSION)\e[0m"
|
||||
return 1
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
|
@@ -3,9 +3,9 @@
|
||||
############## Begin Function Section ##############
|
||||
|
||||
check_online_status() {
|
||||
CHECK_ONLINE_IPS=(1.1.1.1 9.9.9.9 8.8.8.8)
|
||||
for ip in "${CHECK_ONLINE_IPS[@]}"; do
|
||||
if timeout 3 ping -c 1 ${ip} > /dev/null; then
|
||||
CHECK_ONLINE_DOMAINS=('https://github.com' 'https://hub.docker.com')
|
||||
for domain in "${CHECK_ONLINE_DOMAINS[@]}"; do
|
||||
if timeout 6 curl --head --silent --output /dev/null ${domain}; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
Reference in New Issue
Block a user