stdin, stdout, mkstemp
} from 'fs';
+import {
+ openlog, syslog, closelog, LOG_NOTICE, LOG_LOCAL0
+} from 'log';
+
+import { run_plugins } from 'luciplugins';
+
// luci.http module scope
export let HTTP_MAX_CONTENT = 1024*100; // 100 kB maximum content size
if (!this.headers?.['x-content-type-options'])
this.header('X-Content-Type-Options', 'nosniff');
+ /* http header plugins */
+ let log_class = 'http.uc';
+ openlog(log_class);
+ for (let plugin_id, p_output in run_plugins('/luci/plugins/http/headers', 'http_headers_enabled')) {
+
+ /* header plugins shall return e.g.: ['X-Header', 'foo'] */
+ if (type(p_output) !== 'array' || length(p_output) !== 2)
+ continue;
+
+ if (type(p_output[0]) !== 'string' || type(p_output[1]) !== 'string')
+ continue;
+
+ if (!match(p_output[0], /^[A-Za-z0-9-]+$/)) {
+ syslog(LOG_NOTICE|LOG_LOCAL0,
+ sprintf("Invalid header name from plugin %s output: %s", plugin_id, p_output[0]));
+ continue;
+ }
+
+ /* header plugin values shall not contain line-feeds */
+ if (match(p_output[1], /[\r\n]/)) {
+ syslog(LOG_NOTICE|LOG_LOCAL0,
+ sprintf("\\r and/or \\n in plugin %s output", plugin_id));
+ continue;
+ }
+
+ if(!this.headers?.[p_output[0]])
+ this.header(p_output[0], p_output[1]);
+
+ }
+ closelog();
+
this.output('Status: ');
this.output(this.status_code);
this.output(' ');
--- /dev/null
+// SPDX-License-Identifier: Apache-2.0
+
+import {
+ lsdir
+} from 'fs';
+
+import {
+ syslog, LOG_NOTICE, LOG_LOCAL0
+} from 'log';
+
+import { cursor } from 'uci';
+
+
+/* generic plugin handler */
+export function run_plugins(plugin_class_path, plugin_class_enable) {
+ let uci = cursor();
+ const require_path = replace(plugin_class_path, '/', '.');
+
+ if (uci.get('luci_plugins', 'global', 'enabled') == 1 &&
+ uci.get('luci_plugins', 'global', plugin_class_enable) == 1) {
+ const PLUGINS_PATH = '/usr/share/ucode' + plugin_class_path;
+ const results = {};
+
+ for (let fn in lsdir(PLUGINS_PATH)) {
+ const plugin_id = replace(fn, /.uc$/, '');
+ /* plugins shall have a <32_char_UUID_no_hyphens>.uc filename */
+ if (!match(plugin_id, /^[a-f0-9]+$/) || length(plugin_id) !== 32) {
+ syslog(LOG_NOTICE|LOG_LOCAL0,
+ sprintf("Invalid plugin name: %s", plugin_id));
+ continue;
+ }
+
+ if (uci.get('luci_plugins', plugin_id, 'enabled')) {
+ const mod = require(require_path + `.${plugin_id}`);
+ if (type(mod) === 'function') {
+ try {
+ results[plugin_id] = mod(plugin_id);
+ } catch (e) {
+ syslog(LOG_NOTICE|LOG_LOCAL0,
+ sprintf("Could not execute plugin %s: %s",
+ join('/', [PLUGINS_PATH, plugin_id]), e));
+ };
+ }
+ }
+ }
+
+ return results;
+ }
+};