feat(files): 大文件分片上传、停服解压 zip 先列冲突再覆盖、文件和文件夹可下载;导出和下载不再带出 RCON 密码与转发密钥
This commit is contained in:
76 files changed
+10542
-569
No files matched your search
@@ -0,0 +1,58 @@
|
||||
package fileedit
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// What leaves a world mount — a read, a download, a world export, a backup
|
||||
// export — passes the same two guards: the forwarding-secret file
|
||||
// (secretConfigPath) is withheld, and server.properties has its RCON password
|
||||
// redacted (propsPath).
|
||||
//
|
||||
// On a live mount both are matched by the file itself (os.SameFile), not by the
|
||||
// name it was reached under. A plugin runs arbitrary code as the game uid and can
|
||||
// leave a symbolic or hard link to either file anywhere in the world; a name
|
||||
// check alone would hand the secret out under the link's name. A stored archive
|
||||
// has only names, so ArchiveRule matches those.
|
||||
|
||||
// Guard knows the two guarded files of one world mount.
|
||||
type Guard struct {
|
||||
secret, props fs.FileInfo
|
||||
}
|
||||
|
||||
// NewGuard looks the guarded files up in r. One that is missing guards nothing:
|
||||
// no file can be the same file as it.
|
||||
func NewGuard(r *os.Root) Guard {
|
||||
var g Guard
|
||||
if fi, err := r.Stat(secretConfigPath); err == nil {
|
||||
g.secret = fi
|
||||
}
|
||||
if fi, err := r.Stat(propsPath); err == nil {
|
||||
g.props = fi
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// Rule reports whether the file fi describes must be withheld, or sent only
|
||||
// through RedactProps.
|
||||
func (g Guard) Rule(fi fs.FileInfo) (withhold, redact bool) {
|
||||
if g.secret != nil && os.SameFile(g.secret, fi) {
|
||||
return true, false
|
||||
}
|
||||
return false, g.props != nil && os.SameFile(g.props, fi)
|
||||
}
|
||||
|
||||
// ArchiveRule is Rule for an entry of a stored world archive, by its name
|
||||
// cleaned as a path, so "./server.properties" is server.properties too.
|
||||
func ArchiveRule(name string) (withhold, redact bool) {
|
||||
name = path.Clean(name)
|
||||
return name == secretConfigPath, name == propsPath
|
||||
}
|
||||
|
||||
// RedactProps replaces the RCON password in server.properties content with
|
||||
// redactedValue (see redactSecretProps for why a placeholder and not a blank).
|
||||
func RedactProps(content []byte) []byte {
|
||||
return redactSecretProps(propsPath, content)
|
||||
}
|
||||
Reference in new issue
Block a user