This commit is contained in:
Mateusz Gruszczyński committed 2026-10-08 22:22:46 +02:00
1 parent 76cb4acef0
commit 68678e98be
84 files changed
+1519 -325

No files matched your search

+17 -8
View File
@@ -80,8 +80,10 @@
return result;
}
function validatePhpCustomData(customParams, phpValues) {
const size = [...Object.entries(customParams), ...Object.entries(phpValues)]
function validatePhpCustomData(customParams, phpValues, phpAdminValues = {}) {
// Never allow an admin override to conflict with ordinary PHP_VALUE.
if (Object.keys(phpValues).some(name => Object.hasOwn(phpAdminValues, name))) throw new Error(t("webServicePhpValuesInvalid"));
const size = [...Object.entries(customParams), ...Object.entries(phpValues), ...Object.entries(phpAdminValues)]
.reduce((total, [name, value]) => total + name.length + value.length + 2, 0);
if (size > 128 * 1024) throw new Error(t("webServicePhpCustomDataTooLarge"));
}
@@ -156,8 +158,9 @@
for (const id of [
"web-service-php-endpoint", "web-service-php-extensions", "web-service-php-connect-timeout",
"web-service-php-request-timeout", "web-service-php-concurrency", "web-service-php-pass-authorization",
"web-service-php-path-info",
"web-service-php-body-limit", "web-service-php-header-limit", "web-service-php-stderr-limit",
"web-service-php-custom-params", "web-service-php-values"
"web-service-php-custom-params", "web-service-php-values", "web-service-php-admin-values"
]) $(id).disabled = !enabled;
}
@@ -194,9 +197,9 @@
mime_types: {}, default_mime_type: "application/octet-stream", cache_control: null, cache_rules: [], response_headers: {},
try_files: [], rewrites: [], compression: { enabled: null, gzip: null, br: null, zstd: null, deflate: null }, precompressed: { enabled: false, brotli: true, gzip: true }, download_extensions: [],
symlink_policy: "deny", php: {
enabled: false, extensions: ["php"], endpoint: "unix:/run/php/php-fpm.sock", connect_timeout_ms: 1000,
enabled: false, path_info: false, extensions: ["php"], endpoint: "unix:/run/php/php-fpm.sock", connect_timeout_ms: 1000,
request_timeout_ms: 30000, max_concurrent_requests: 64, pass_authorization: true, max_request_body_bytes: 0,
max_response_header_bytes: 65536, stderr_log_bytes: 4096, custom_params: {}, php_values: {}
max_response_header_bytes: 65536, stderr_log_bytes: 4096, custom_params: {}, php_values: {}, php_admin_values: {}
},
htaccess: { enabled: false, filename: ".htaccess", scan_subdirectories: true, strict: false },
hardening: { block_common_attacks: false, strip_unnecessary_headers: false }
@@ -241,6 +244,7 @@
$("web-service-precompressed-gzip").checked = item.precompressed?.gzip !== false;
$("web-service-download-extensions").value = (item.download_extensions || []).join("\n");
$("web-service-php-enabled").checked = item.php?.enabled === true;
$("web-service-php-path-info").checked = item.php?.path_info === true;
$("web-service-php-endpoint").value = item.php?.endpoint || "unix:/run/php/php-fpm.sock";
$("web-service-php-extensions").value = (item.php?.extensions || ["php"]).join(", ");
$("web-service-php-connect-timeout").value = item.php?.connect_timeout_ms ?? 1000;
@@ -252,6 +256,7 @@
$("web-service-php-stderr-limit").value = item.php?.stderr_log_bytes ?? 4096;
$("web-service-php-custom-params").value = mapLines(item.php?.custom_params);
$("web-service-php-values").value = mapLines(item.php?.php_values);
$("web-service-php-admin-values").value = mapLines(item.php?.php_admin_values);
$("web-service-symlink-policy").value = item.symlink_policy || "deny";
$("web-service-htaccess-enabled").checked = item.htaccess?.enabled === true;
$("web-service-htaccess-filename").value = item.htaccess?.filename || ".htaccess";
@@ -280,12 +285,14 @@
preset.php.request_timeout_ms = Number($("web-service-php-request-timeout").value || preset.php.request_timeout_ms);
preset.php.max_concurrent_requests = Number($("web-service-php-concurrency").value || preset.php.max_concurrent_requests);
preset.php.pass_authorization = $("web-service-php-pass-authorization").checked;
preset.php.path_info = $("web-service-php-path-info").checked;
preset.php.max_request_body_bytes = Number($("web-service-php-body-limit").value || 0);
preset.php.max_response_header_bytes = Number($("web-service-php-header-limit").value || preset.php.max_response_header_bytes);
preset.php.stderr_log_bytes = Number($("web-service-php-stderr-limit").value || 0);
preset.php.custom_params = parseFastCgiParams($("web-service-php-custom-params").value);
preset.php.php_values = parsePhpValues($("web-service-php-values").value);
validatePhpCustomData(preset.php.custom_params, preset.php.php_values);
preset.php.php_admin_values = parsePhpValues($("web-service-php-admin-values").value);
validatePhpCustomData(preset.php.custom_params, preset.php.php_values, preset.php.php_admin_values);
preset.hardening.block_common_attacks = $("web-service-hardening-attacks").checked;
preset.hardening.strip_unnecessary_headers = $("web-service-hardening-headers").checked;
populateSettings(preset);
@@ -423,6 +430,7 @@
},
php: {
enabled: phpEnabled,
path_info: $("web-service-php-path-info").checked,
extensions: lines($("web-service-php-extensions").value).map(value => value.replace(/^\./, "").toLowerCase()),
endpoint: $("web-service-php-endpoint").value.trim() || "unix:/run/php/php-fpm.sock",
connect_timeout_ms: Number($("web-service-php-connect-timeout").value || 1000),
@@ -433,10 +441,11 @@
max_response_header_bytes: Number($("web-service-php-header-limit").value || 65536),
stderr_log_bytes: Number($("web-service-php-stderr-limit").value || 0),
custom_params: parseFastCgiParams($("web-service-php-custom-params").value),
php_values: parsePhpValues($("web-service-php-values").value)
php_values: parsePhpValues($("web-service-php-values").value),
php_admin_values: parsePhpValues($("web-service-php-admin-values").value)
}
};
validatePhpCustomData(item.php.custom_params, item.php.php_values);
validatePhpCustomData(item.php.custom_params, item.php.php_values, item.php.php_admin_values);
if (phpEnabled && item.symlink_policy !== "deny") throw new Error(t("webServicePhpSymlinkConflict"));
const next = structuredClone(envelope.config.web_services || []);
const duplicate = next.find(service => service.id === item.id && service.id !== editing);