⛅ Sync 2026-09-05 14:47:29

This commit is contained in:
github-actions[bot] committed 2026-09-05 14:47:29 +08:00
1 parent 542a97782d
commit c5b7496c5d
19 files changed
+219 -230

No files matched your search

+8 -151
View File
@@ -1,156 +1,13 @@
server:
minSearchLength: 3 # minimum length of search query to begin searching (default: 3)
disableUpdateCheck: false # disables backend update check service
numImageProcessors: 4 # number of concurrent image processing jobs used to create previews, default is number of cpu cores available.
socket: "" # socket to listen on
tlsKey: "" # path to TLS key
tlsCert: "" # path to TLS cert
disablePreviews: false # disable all previews thumbnails, simple icons will be used
disablePreviewResize: false # disable resizing of previews for faster loading over slow connections
disableTypeDetectionByHeader: false # disable type detection by header, useful if filesystem is slow.
port: 8989
baseURL: "/"
logging:
- levels: "" # separated list of log levels to enable. (eg. "info|warning|error|debug")
apiLevels: "" # separated list of log levels to enable for the API. (eg. "info|warning|error")
output: "stdout" # output location. (eg. "stdout" or "path/to/file.log")
noColors: false # disable colors in the output
json: false # output in json format
utc: false # use UTC time in the output instead of local time
debugMedia: false # output ffmpeg stdout for media integration -- careful can produces lots of output!
database: "/etc/filebrowser/database.db" # path to the database file
sources: # validate:required,dive
- path: "/"
name: "Root" # display name
database: "/etc/filebrowser/database.db"
sources:
- path: "/" # Do not use a root "/" directory or include the "/var" folder
config:
denyByDefault: false # deny access unless an "allow" access rule was specifically created.
private: false # designate as source as private -- currently just means no sharing permitted.
disabled: false # disable the source, this is useful so you don't need to remove it from the config file
indexingIntervalMinutes: 0 # optional manual overide interval in minutes to re-index the source
disableIndexing: false # disable the indexing of this source
maxWatchers: 0 # number of concurrent watchers to use for this source, currently not supported
neverWatchPaths: []
exclude: # exclude files and folders from indexing, if include is not set
hidden: false # exclude hidden files and folders.
ignoreZeroSizeFolders: false # ignore folders with 0 size
filePaths: []
folderPaths: []
fileNames: []
folderNames: []
fileEndsWith: []
folderEndsWith: []
fileStartsWith: []
folderStartsWith: []
include: # include files and folders from indexing, if exclude is not set
rootFolders: []
rootFiles: []
defaultUserScope: "/" # default "/" should match folders under path
defaultEnabled: false # should be added as a default source for new users?
createUserDir: false # create a user directory for each user
externalUrl: "" # used by share links if set (eg. http://mydomain.com)
internalUrl: "" # used by integrations if set, this is the base domain that an integration service will use to communicate with filebrowser (eg. http://localhost:8080)
cacheDir: "tmp" # path to the cache directory, used for thumbnails and other cached files
maxArchiveSize: 50 # max pre-archive combined size of files/folder that are allowed to be archived (in GB)
defaultEnabled: true
auth:
tokenExpirationHours: 2 # time in hours each web UI session token is valid for. Default is 2 hours.
methods:
proxy: # validate:omitempty
enabled: false
createUser: false # create user if not exists
header: "" # required header to use for authentication. Security Warning: FileBrowser blindly accepts the header value as username.
logoutRedirectUrl: "" # if provider logout url is provided, filebrowser will also redirect to logout url. Custom logout query params are respected.
noauth: false # if set to true, overrides all other auth methods and disables authentication
password: # validate:omitempty
enabled: true
minLength: 3 # minimum pasword length required, default is 5. validate:omitempty
signup: false # allow signups on login page if enabled -- not secure. validate:omitempty
recaptcha: # recaptcha config, only used if signup is enabled validate:omitempty
host: "" # validate:required
key: "" # validate:required
secret: "" # validate:required
enforcedOtp: false # if set to true, TOTP is enforced for all password users users. Otherwise, users can choose to enable TOTP.
oidc: # validate:omitempty
enabled: false # whether to enable OIDC authentication
clientId: "**hidden**" # secret: client id of the OIDC application
clientSecret: "**hidden**" # secret: client secret of the OIDC application
issuerUrl: "" # authorization URL of the OIDC provider
scopes: "openid email profile" # scopes to request from the OIDC provider
userIdentifier: "preferred_username" # the field value to use as the username. Default is "preferred_username", can also be "email" or "username", or "phone"
disableVerifyTLS: false # disable TLS verification for the OIDC provider. This is insecure and should only be used for testing.
logoutRedirectUrl: "" # if provider logout url is provided, filebrowser will also redirect to logout url. Custom logout query params are respected.
createUser: false # create user if not exists
adminGroup: "" # if set, users in this group will be granted admin privileges.
groupsClaim: "groups" # the JSON field name to read groups from. Default is "groups"
key: "**hidden**" # secret: the key used to sign the JWT tokens. If not set, a random key will be generated.
adminUsername: "admin" # secret: the username of the admin user. If not set, the default is "admin".
adminPassword: "admin" # secret: the password of the admin user. If not set, the default is "admin".
totpSecret: "**hidden**" # secret: secret used to encrypt TOTP secrets
frontend:
name: "FileBrowser Quantum" # display name
disableDefaultLinks: false # disable default links in the sidebar
disableUsedPercentage: false # disable used percentage for the sources in the sidebar
externalLinks:
- text: "Help" # the text to display on the link validate:required
title: "" # the title to display on hover
url: "https://github.com/gtsteffaniak/filebrowser" # the url to link to validate:required
disableNavButtons: false # disable the nav buttons in the sidebar
styling:
customCSS: "" # if a valid path to a css file is provided, it will be applied for all users. (eg. "reduce-rounded-corners.css")
lightBackground: "#f5f5f5" # specify a valid CSS color property value to use as the background color in light mode
darkBackground: "#141D24" # Specify a valid CSS color property value to use as the background color in dark mode
customThemes: # A list of custom css files that each user can select to override the default styling. if "default" is key name then it will be the default option.
default:
description: "The default theme" # The description of the theme to display in the UI.
css: "" # The css file path and filename to use for the theme.
alternative:
description: "Reduce rounded corners" # The description of the theme to display in the UI.
css: "reduce-rounded-corners.css" # The css file path and filename to use for the theme.
favicon: "" # path to a favicon to use for the frontend
description: "FileBrowser Quantum is a file manager for the web which can be used to manage files on your server" # description that shows up in html head meta description
adminUsername: admin
adminPassword: "admin"
userDefaults:
editorQuickSave: false # show quick save button in editor
hideSidebarFileActions: false # hide the file actions in the sidebar
disableQuickToggles: false # disable the quick toggles in the sidebar
disableSearchOptions: false # disable the search options in the search bar
stickySidebar: true # keep sidebar open when navigating
darkMode: true # should dark mode be enabled
locale: "zhCN" # language to use: eg. de, en, or fr
viewMode: "normal" # view mode to use: eg. normal, list, grid, or compact
singleClick: false # open directory on single click, also enables middle click to open in new tab
showHidden: false # show hidden files in the UI. On windows this includes files starting with a dot and windows hidden files
dateFormat: false # when false, the date is relative, when true, the date is an exact timestamp
gallerySize: 3 # 0-9 - the size of the gallery thumbnails
themeColor: "var(--blue)" # theme color to use: eg. #ff0000, or var(--red), var(--purple), etc
quickDownload: false # show icon to download in one click
disablePreviewExt: "" # space separated list of file extensions to disable preview for
disableViewingExt: "" # space separated list of file extensions to disable viewing for
lockPassword: false # disable the user from changing their password
disableSettings: false # disable the user from viewing the settings page
preview:
disableHideSidebar: false
highQuality: false
image: false
video: false
motionVideoPreview: false
office: false
popup: false
autoplayMedia: false
defaultMediaPlayer: false
folder: false
permissions:
api: false
admin: false
modify: false
share: false
realtime: false
loginMethod: "password" # login method to use: eg. password, proxy, oidc
disableUpdateNotifications: false # disable update notifications banner for admin users
deleteWithoutConfirming: false # delete files without confirmation
fileLoading: # upload and download settings
maxConcurrentUpload: 10
uploadChunkSizeMb: 10
clearAll: false
disableOnlyOfficeExt: "" # list of file extensions to disable onlyoffice editor for
customTheme: "" # Name of theme to use chosen from custom themes config.
showSelectMultiple: false # show select multiple files on desktop
debugOffice: false # debug onlyoffice editor
ui:
locale: "cn"
+3 -1
View File
@@ -18,9 +18,11 @@ start() {
local listen_port root_path base_url
config_get listen_port "config" "listen_port" "8989"
config_get root_path "config" "root_path" "/"
config_get base_url "config" "base_url" "/"
echo "Starting filebrowser..."
sed -e "s/ port:.*/ port:$listen_port/" \
-e "s, - path:.*, - path:\"$root_path\"," \
-i "$CONF_PATH"
start-stop-daemon -S -q -b -m -p "$PID_FILE" -x "$PROG" -- -c "$CONF_PATH"
}
@@ -49,17 +49,24 @@ return view.extend({
s = m.section(form.TypedSection);
s.anonymous = true;
s.render = function() {
poll.add(function() {
return Promise.resolve().then(function() {
let view = document.getElementById('service_status');
view.innerHTML = renderStatus(data.isRunning, webport);
});
});
poll.add(function() {
return fs.stat('/var/run/filebrowser.pid').then(function(stat) {
let view = document.getElementById('service_status');
if (view) {
view.innerHTML = renderStatus(stat, webport);
}
}).catch(function() {
let view = document.getElementById('service_status');
if (view) {
view.innerHTML = renderStatus(null, webport);
}
});
});
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
E('p', { id: 'service_status' }, _('Collecting data...'))
]);
}
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
E('p', { id: 'service_status' }, _('Collecting data...'))
]);
};
s = m.section(form.NamedSection, 'config', 'filebrowser');
-5
View File
@@ -8,11 +8,6 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI page for IPK upload
LUCI_DEPENDS:=+luci-lib-fs
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-filetransfer
PKG_VERSION:=1
PKG_RELEASE:=1
include $(TOPDIR)/feeds/luci/luci.mk
@@ -9,5 +9,7 @@ module("luci.controller.filetransfer", package.seeall)
function index()
entry({"admin", "system", "filetransfer"}, form("filetransfer"), _("FileTransfer"), 89).dependent = true
local page = entry({"admin", "system", "filetransfer"}, form("filetransfer"), _("FileTransfer"), 89)
page.dependent = true
page.acl_depends = { "luci-app-filetransfer" }
end
@@ -91,16 +91,6 @@ elseif luci.http.formvalue("download") then
Download()
end
local function getSizeStr(size)
local i = 0
local byteUnits = {' kB', ' MB', ' GB', ' TB'}
repeat
size = size / 1024
i = i + 1
until(size <= 1024)
return string.format("%.1f", size) .. byteUnits[i]
end
local inits, attr = {}
for i, f in ipairs(fs.glob("/tmp/upload/*")) do
attr = fs.stat(f)
@@ -109,7 +99,7 @@ for i, f in ipairs(fs.glob("/tmp/upload/*")) do
inits[i].name = fs.basename(f)
inits[i].mtime = os.date("%Y-%m-%d %H:%M:%S", attr.mtime)
inits[i].modestr = attr.modestr
inits[i].size = getSizeStr(attr.size)
inits[i].size = tostring(attr.size)
inits[i].remove = 0
inits[i].install = false
end
@@ -122,9 +112,8 @@ form.submit = false
tb = form:section(Table, inits)
nm = tb:option(DummyValue, "name", translate("File name"))
mt = tb:option(DummyValue, "mtime", translate("Modify time"))
ms = tb:option(DummyValue, "modestr", translate("Attributes"))
ms = tb:option(DummyValue, "modestr", translate("Mode string"))
sz = tb:option(DummyValue, "size", translate("Size"))
btnrm = tb:option(Button, "remove", translate("Remove"))
btnrm.render = function(self, section, scope)
self.inputstyle = "remove"
+1
View File
@@ -0,0 +1 @@
zh_Hans
-1
View File
@@ -1 +0,0 @@
zh-cn
@@ -1,15 +1,5 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Choose local file:"
msgstr "选择本地文件:"
@@ -38,17 +28,17 @@ msgstr "文件传输"
msgid "Install"
msgstr "安装"
msgid "Attributes"
msgstr "属性"
msgid "Mode string"
msgstr "模式字符串"
msgid "Modify time"
msgstr "修改时间"
msgid "No specify upload file."
msgstr "未指定上传文件。"
msgstr "未指定上传文件"
msgid "Path on Route:"
msgstr "路由根目录:"
msgstr "路由上目录"
msgid "Remove"
msgstr "移除"
@@ -1,6 +0,0 @@
#!/bin/sh
sed -i 's/cbi.submit\"] = true/cbi.submit\"] = \"1\"/g' /usr/lib/lua/luci/dispatcher.lua
rm -f /tmp/luci-indexcache
exit 0
@@ -0,0 +1,11 @@
{
"luci-app-filetransfer": {
"description": "Grant UCI access for luci-app-filetransfer",
"read": {
"uci": [ "filetransfer" ]
},
"write": {
"uci": [ "filetransfer" ]
}
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap
FOOTSTRAP_VERSION?=
ifneq ($(FOOTSTRAP_VERSION),)
PKG_VERSION:=$(FOOTSTRAP_VERSION)
PKG_RELEASE:=57
PKG_RELEASE:=58
endif
LUCI_TITLE:=Footstrap Theme
@@ -43,17 +43,22 @@ const _uciCommit = rpc.declare({ object: 'uci', method: 'commit', params: [ 'con
* Router-side, like the login photo and for the same reason — a file cannot live in localStorage,
* and a pattern is something a router wears. The path is a fixed server-side constant matched
* exactly by the rpcd ACL, so nothing user-controlled reaches a path. It lives under /etc so a
* package upgrade cannot delete it (keep.d carries it across a sysupgrade), and the served name
* ends in .svg because uhttpd types a file by extension.
* package upgrade cannot delete it (keep.d carries it across a sysupgrade). It keeps the .svg name
* for its own sake — the CGI handler that now serves it (root/www/cgi-bin) sets Content-Type
* itself and does not rely on uhttpd's by-extension typing the way the login photo's /www symlink
* still does.
*
* How it is made to fit is 15-wallpaper.css's mask, not anything done to the bytes: the file
* supplies the alpha and the theme the colour, so one upload reads correctly in both modes and
* under every palette.
*
* What is refused: an SVG is a document, not a picture, and while a masked or background image
* never executes script, the same file fetched from its own URL would. Uploading already needs an
* authenticated admin session with uci write rights, so this is defence in depth — but the check is
* cheap and the failure mode is somebody else's browser. */
* never executes script, the same file fetched from its own URL would (OpenWrt forum thread
* 251930) — which is what the server-side handler (root/www/cgi-bin) now closes with response
* headers a browser will not execute. THIS check runs in the uploading admin's OWN browser and is
* not a defence at all: a `curl` POST to the same cgi-io path skips it entirely, and the rpcd ACL
* authorises that POST regardless of what wrote it. It exists only so an admin who uploads a bad
* file by mistake is told so before it lands, and the cost of running it is cheap. */
const PAT_PATH = '/etc/footstrap/pattern.svg'; /* cgi-upload target; the ACL grants exactly this */
const PAT_MAX = 512 * 1024; /* a tile that has to reach a router's flash and then every page load */
/* What makes an uploaded SVG unacceptable, decided on the PARSED document and not on its text: a
@@ -65,19 +70,30 @@ const PAT_MAX = 512 * 1024; /* a tile that has to reach a router's flash
* no subresource is fetched, no handler is bound. So the questions are exact ones about nodes:
*
* - is it an SVG at all (a parsererror, or a root that is not <svg>, is not an image)
* - does it carry an element that executes or embeds (script, foreignObject, iframe, …)
* - does it carry an element that executes or embeds (script, foreignObject, iframe, style, …)
* - does it carry a real event-handler attribute — `^on[a-z]+$`
* - does any value start a `javascript:` url
* - does any href point off this router; `#fragment` and `data:` stay allowed, being how a tile
* refers to its own <defs> and embeds a bitmap
* - does any href point off this router — a leading `//`, or a `data:`/`blob:`/`about:` payload
* - does any element carry a `style` attribute
*
* The check is for the way the file can be reached that a mask does not cover: its own URL, opened
* directly, same-origin with the session.
*
* `animate`/`set` are listed for a second reason as well: they can retarget an attribute at run
* time (`<set attributename="href" to="javascript:…">`), and a tile that animates repaints a
* full-viewport layer behind every page. */
const PAT_BAD_TAGS = [ 'script', 'foreignobject', 'iframe', 'embed', 'object', 'audio', 'video', 'animate', 'set' ];
* full-viewport layer behind every page.
*
* `style` is refused both as an ELEMENT and as an ATTRIBUTE: a `<style>@import
* url("//attacker/x.css")</style>` reaches off-router with no script and no href at all, and a
* `style="…url(…)…"` attribute does the same per-element. `data:`/`blob:`/`about:` were allowed
* through `href`/`xlink:href` before this pass, on the theory that a tile only ever uses `data:` to
* embed its own bitmap — closed anyway, because the same scheme admits `data:text/html` and
* `data:image/svg+xml`, and telling those apart from a `data:image/png` bitmap means parsing the
* URI's own MIME token, which is exactly the kind of grammar-guessing this file avoids everywhere
* else. The cost is real: an admin embedding a bitmap inside the tile now needs a second uploaded
* asset referenced by a same-origin URL instead of a `data:` href — the tile itself is unaffected,
* since 15-wallpaper.css never used one. */
const PAT_BAD_TAGS = [ 'script', 'foreignobject', 'iframe', 'embed', 'object', 'audio', 'video', 'animate', 'set', 'style' ];
const SVG_NS = 'http://www.w3.org/2000/svg';
/* null if the parsed document is fine, otherwise the sentence to show. */
@@ -118,8 +134,17 @@ function _svgObjection(text) {
* refuse files that do nothing. */
if ((/^on[a-z]+$/).test(n)) return refused;
if ((/^javascript:/i).test(v)) return refused;
/* off-router reference. A leading `//` is protocol-relative and just as external. */
if ((/(?:^|:)href$/).test(n) && (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i).test(v)) return refused;
/* a `style=""` attribute reaches the same `url()` grammar as a `<style>` element,
* per-element instead of per-document — refused for the same reason that tag is. */
if (n === 'style') return refused;
if ((/(?:^|:)href$/).test(n)) {
/* off-router reference. A leading `//` is protocol-relative and just as external. */
if ((/^(?:[a-z][a-z0-9+.-]*:)?\/\//i).test(v)) return refused;
/* `data:`/`blob:`/`about:` can carry a second document (text/html, image/svg+xml)
* behind an href that looks like a same-document reference — see the comment above
* PAT_BAD_TAGS for why this is a blanket refusal and not a MIME-token check. */
if ((/^(?:data|blob|about):/i).test(v)) return refused;
}
}
}
return null;
@@ -438,7 +438,12 @@ function resetToBuiltin() {
* layer — one admin uploads once and every device sees it, pre-login included. So they are absent
* from AXIS_KEYS, snapshotAxes() and matchesSavedDefault(), and must not move the Save button. */
const PAT_SERVE = '/luci-static/footstrap/pattern.svg'; /* the uhttpd symlink the uci-default makes */
/* NOT a /www symlink, unlike BG_SERVE below: an SVG served as a plain static file is a same-origin
* document that runs script opened directly (OpenWrt forum thread 251930). This CGI handler reads
* the fixed /etc/footstrap/pattern.svg path itself and answers with CSP 'none' + sandbox and
* nosniff, headers uhttpd cannot attach to a static file — see the uci-default and the handler for
* the rest of the reasoning. Painting stays exactly as before: a URL is a URL to a mask-image. */
const PAT_SERVE = '/cgi-bin/luci-theme-footstrap-pattern';
function currentPattern() {
const t = prefs.sd('pattern');
return (typeof t === 'string' && BG_TOKEN_RE.test(t)) ? t : '';
@@ -454,7 +459,10 @@ function applyPattern(tok) {
prefs.setSD('pattern', tok || '');
}
const BG_SERVE = '/luci-static/footstrap/bg'; /* the uhttpd symlink the uci-default makes */
/* Still the plain uhttpd symlink the uci-default makes, unlike PAT_SERVE above: fs-assets.js
* re-encodes every login-bg upload to a JPEG on a canvas before it is sent, so the stored bytes
* are pixels only — there is no script grammar left in a raster for a direct hit to run. */
const BG_SERVE = '/luci-static/footstrap/bg';
/* the cache-bust token charset, an md5/sha hex string. One copy here; head.ut's ucode sanitiser
* and the pre-paint inline script keep their own identical copies unavoidably, running before this
* module — see the axes contract in head.ut. */
@@ -1,7 +1,9 @@
#!/bin/sh
# Registration, plus the three symlinks that expose what the admin uploads. Nothing here migrates a
# router off an older footstrap: OpenWrt expects a sysupgrade rather than a package upgrade.
# Registration, plus the two symlinks that expose what the admin uploads (a third, the pattern, is
# deliberately NOT one — see below). Nothing here migrates a router off an older footstrap: OpenWrt
# expects a sysupgrade rather than a package upgrade — the one exception is the stale pattern
# symlink itself, removed below because leaving it would keep a reported security hole open.
changed=0
@@ -23,13 +25,22 @@ fi
[ "$changed" = 1 ] && uci commit luci
# uhttpd serves /www only, so the admin's uploads live in /etc — where a sysupgrade keeps them
# (lib/upgrade/keep.d) — and are reached through symlinks. The pattern keeps its .svg name: uhttpd
# types a response by extension, and an SVG sent as octet-stream paints nowhere.
# (lib/upgrade/keep.d) — and are reached through symlinks, EXCEPT the pattern (below).
#
# The pattern is deliberately NOT symlinked into /www: an SVG is a document, and served as one
# through a plain same-origin URL it runs as a script with the admin's session (OpenWrt forum
# thread 251930). It is instead read by cgi-bin/luci-theme-footstrap-pattern, which answers with
# CSP 'none' + sandbox and nosniff — headers uhttpd cannot attach to a static file. The login
# background stays a plain symlink: fs-assets.js re-encodes every upload to a JPEG on a canvas
# first, so there is no script grammar left in the bytes for a direct hit to run.
mkdir -p /etc/footstrap
if [ -d /www/luci-static/footstrap ]; then
ln -sf /etc/footstrap/login-bg /www/luci-static/footstrap/bg
ln -sf /etc/footstrap/pattern.svg /www/luci-static/footstrap/pattern.svg
ln -sfn /etc/footstrap/fonts /www/luci-static/footstrap/fonts
fi
# Clean up a pre-0.15 install's stale pattern symlink — see the header comment above for why this
# is the one migration this script makes. `-L` only: never remove a real file some other install
# step could have left at that path.
[ -L /www/luci-static/footstrap/pattern.svg ] && rm -f /www/luci-static/footstrap/pattern.svg
exit 0
@@ -0,0 +1,43 @@
#!/bin/sh
# Serves the admin-uploaded wallpaper pattern with headers a browser will not execute: opened
# directly, the /www symlink this replaces was a same-origin document with an authenticated LuCI
# session reachable from it (OpenWrt forum thread 251930, confirmed on a stand — a marker SVG set
# document.title, read location.origin as the router's, and reached document.cookie, pre-login
# too, since /www needs no session). The theme's own rendering never hits this: 15-wallpaper.css
# paints the same file through mask-image or a tiled background-image, and neither ever runs
# script inside it — the exposure was only the direct URL, which is what CSP 'none' + sandbox and
# nosniff below close, without touching how the mask/background paints it.
#
# Deliberately unauthenticated, on purpose and not an oversight: the pattern paints before login
# too (head.ut's pre-paint, from window.__fsSD). That is safe here ONLY because this script takes
# NO input at all — FILE below is a shell constant, never $QUERY_STRING, $PATH_INFO or anything
# else request-supplied — so there is nothing to traverse and nothing else this handler can be
# made to read.
#
# The login background (/etc/footstrap/login-bg) stays a plain /www symlink and does NOT get this
# treatment: fs-assets.js re-encodes every upload to a JPEG on a canvas before it is sent, so the
# stored bytes are pixels only and there is no script grammar left in the file for a direct hit to
# run — see docs/package.md.
FILE=/etc/footstrap/pattern.svg
if [ ! -r "$FILE" ]; then
printf 'Status: 404 Not Found\r\n'
printf 'Content-Type: text/plain\r\n'
printf '\r\n'
exit 0
fi
printf 'Status: 200 OK\r\n'
printf 'Content-Type: image/svg+xml\r\n'
# Cacheable forever, because the URL is not stable: fs-axes.js appends `?v=<token>` and the token
# changes with every upload, so a new file is a new URL. Without this the /www symlink's ETag and
# Last-Modified were gone and the tile was re-fetched on EVERY page load - a background image on a
# router that serves it off flash with no gzip, which is the cost this handler must not add.
printf 'Cache-Control: public, max-age=31536000, immutable\r\n'
printf 'X-Content-Type-Options: nosniff\r\n'
printf "Content-Security-Policy: default-src 'none'; sandbox\r\n"
printf '\r\n'
cat "$FILE"
exit 0
@@ -231,7 +231,11 @@
sd.pattern is whitelisted to hex above, so nothing user-controlled reaches
the url(). */
const pu = sd.pattern;
if (pu) root.style.setProperty('--fs-pattern-url', 'url("/luci-static/footstrap/pattern.svg?v=' + pu + '")');
/* /cgi-bin, not a /www symlink: a plain static SVG is a same-origin document
that runs script opened directly (OpenWrt forum thread 251930); this path
is the CGI handler that answers with CSP 'none' + sandbox instead — see
fs-axes.js's PAT_SERVE, which this string must keep matching. */
if (pu) root.style.setProperty('--fs-pattern-url', 'url("/cgi-bin/luci-theme-footstrap-pattern?v=' + pu + '")');
const psRaw = lsGet('fs-pattern-size');
const ps = (psRaw !== null) ? parseInt(psRaw, 10) : sd.pattern_size;
if (ps >= 40 && ps <= 1600 && ps !== 440) root.style.setProperty('--fs-pattern-size', ps + 'px');
+2 -2
View File
@@ -2,8 +2,8 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=tcp-brutal
PKG_VERSION:=1.0.3
PKG_RELEASE:=1
PKG_VERSION:=2.0.0
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/apernet/tcp-brutal/tar.gz/v$(PKG_VERSION)?
+55 -4
View File
@@ -37,12 +37,37 @@ endif
PKG_NAME:=pgyvpn
PKG_VERSION:=3.1.0
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=pgyvpnsvr
PKG_SOURCE_URL:=https://mirrors.oray.com/orayos/packages/$(PKG_NAME)/$(PKG_ARCH_PGYYPN)/$(PKG_VERSION)/bin
PKG_HASH:=skip
OPENSSL_COMPAT_VERSION:=1.1.1w
OPENSSL_COMPAT_SOURCE:=openssl-$(OPENSSL_COMPAT_VERSION).tar.gz
OPENSSL_COMPAT_HASH:=cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8
OPENSSL_COMPAT_TARGET:=linux-generic32
ifeq ($(ARCH),arm)
OPENSSL_COMPAT_TARGET:=linux-armv4
endif
ifeq ($(ARCH),aarch64)
OPENSSL_COMPAT_TARGET:=linux-aarch64
endif
ifeq ($(ARCH),mips)
OPENSSL_COMPAT_TARGET:=linux-mips32
endif
ifeq ($(ARCH),mipsel)
OPENSSL_COMPAT_TARGET:=linux-mips32
endif
ifeq ($(ARCH),i386)
OPENSSL_COMPAT_TARGET:=linux-x86
endif
ifeq ($(ARCH),x86_64)
OPENSSL_COMPAT_TARGET:=linux-x86_64
endif
PKG_FLAGS:=nonshared
PKG_MAINTAINER:=Oray <developer@oray.com>
include $(INCLUDE_DIR)/package.mk
@@ -52,7 +77,7 @@ define Package/pgyvpn
CATEGORY:=Network
SUBMENU:=VPN
DEPENDS:=@(arm||aarch64||mips||mipsel||i386||x86_64) \
+iptables +libc +libopenssl +librt \
+iptables +libc +librt \
+libpthread +libstdcpp +kmod-tun
TITLE:=PuGongYing VPN, Fast networking
URL:=https://pgy.oray.com/
@@ -68,16 +93,39 @@ define Download/extra
URL:=$(PKG_SOURCE_URL)
HASH:=skip
endef
define Download/openssl-compat
FILE:=$(OPENSSL_COMPAT_SOURCE)
URL:=https://www.openssl.org/source/old/1.1.1
HASH:=skip
endef
$(eval $(call Download,extra))
$(eval $(call Download,openssl-compat))
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(TAR) -C $(PKG_BUILD_DIR) -xf $(DL_DIR)/$(OPENSSL_COMPAT_SOURCE)
mv $(DL_DIR)/{pgyvpn_oraysl,pgyvpnsvr} $(PKG_BUILD_DIR)
chmod +x $(PKG_BUILD_DIR)/{pgyvpn_oraysl,pgyvpnsvr}
endef
define Build/Configure
( cd $(PKG_BUILD_DIR)/openssl-$(OPENSSL_COMPAT_VERSION) && \
CC="$(TARGET_CC)" \
./Configure $(OPENSSL_COMPAT_TARGET) \
--prefix=/usr \
--libdir=lib \
--cross-compile-prefix="$(TARGET_CROSS)" \
shared no-tests no-engine no-async no-comp no-asm \
$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(TARGET_LDFLAGS) \
)
endef
define Build/Compile
true
+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/openssl-$(OPENSSL_COMPAT_VERSION) \
CC="$(TARGET_CC)" \
SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \
build_libs
endef
define Package/pgyvpn/install
@@ -86,8 +134,11 @@ define Package/pgyvpn/install
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/usr/share/pgyvpn
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/pgyvpn_oraysl $(1)/usr/sbin
$(CP) $(PKG_BUILD_DIR)/{pgyvpn_oraysl,pgyvpnsvr} $(1)/usr/sbin
$(INSTALL_DATA) $(PKG_BUILD_DIR)/openssl-$(OPENSSL_COMPAT_VERSION)/libssl.so.1.1 $(1)/usr/lib
$(INSTALL_DATA) $(PKG_BUILD_DIR)/openssl-$(OPENSSL_COMPAT_VERSION)/libcrypto.so.1.1 $(1)/usr/lib
$(INSTALL_BIN) ./files/etc/init.d/* $(1)/etc/init.d
$(INSTALL_CONF) ./files/etc/config/* $(1)/etc/config
$(INSTALL_BIN) ./files/etc/hotplug.d/iface/* $(1)/etc/hotplug.d/iface