Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b97a1088fa | ||
|
|
b77bed3324 | ||
|
|
a2b7c85a1f | ||
|
|
b28533f850 | ||
|
|
bd8c7e538a | ||
|
|
89e48cff24 | ||
|
|
ae90a7b7b6 | ||
|
|
6fc1be04da |
@@ -68,12 +68,16 @@ you may also want these, especially on servers:
|
|||||||
|
|
||||||
## notes
|
## notes
|
||||||
|
|
||||||
|
general:
|
||||||
|
* paper-printing is affected by dark/light-mode! use lightmode for color, darkmode for grayscale
|
||||||
|
* because no browsers currently implement the media-query to do this properly orz
|
||||||
|
|
||||||
|
browser-specific:
|
||||||
* iPhone/iPad: use Firefox to download files
|
* iPhone/iPad: use Firefox to download files
|
||||||
* Android-Chrome: increase "parallel uploads" for higher speed (android bug)
|
* Android-Chrome: increase "parallel uploads" for higher speed (android bug)
|
||||||
* Android-Firefox: takes a while to select files (their fix for ☝️)
|
* Android-Firefox: takes a while to select files (their fix for ☝️)
|
||||||
* Desktop-Firefox: ~~may use gigabytes of RAM if your files are massive~~ *seems to be OK now*
|
* Desktop-Firefox: ~~may use gigabytes of RAM if your files are massive~~ *seems to be OK now*
|
||||||
* paper-printing is affected by dark/light-mode! use lightmode for color, darkmode for grayscale
|
* Desktop-Firefox: may stop you from deleting folders you've uploaded until you visit `about:memory` and click `Minimize memory usage`
|
||||||
* because no browsers currently implement the media-query to do this properly orz
|
|
||||||
|
|
||||||
|
|
||||||
## status
|
## status
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ def run_argparse(argv, formatter):
|
|||||||
--ls '**' # list all files which are possible to read
|
--ls '**' # list all files which are possible to read
|
||||||
--ls '**,*,ln' # check for dangerous symlinks
|
--ls '**,*,ln' # check for dangerous symlinks
|
||||||
--ls '**,*,ln,p,r' # check, then start normally if safe
|
--ls '**,*,ln,p,r' # check, then start normally if safe
|
||||||
|
\033[0m
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -377,6 +378,9 @@ def main(argv=None):
|
|||||||
+ " (if you crash with codec errors then that is why)"
|
+ " (if you crash with codec errors then that is why)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if WINDOWS and sys.version_info < (3, 6):
|
||||||
|
al.no_scandir = True
|
||||||
|
|
||||||
# signal.signal(signal.SIGINT, sighandler)
|
# signal.signal(signal.SIGINT, sighandler)
|
||||||
|
|
||||||
SvcHub(al).run()
|
SvcHub(al).run()
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 11, 8)
|
VERSION = (0, 11, 10)
|
||||||
CODENAME = "the grid"
|
CODENAME = "the grid"
|
||||||
BUILD_DT = (2021, 6, 6)
|
BUILD_DT = (2021, 6, 8)
|
||||||
|
|
||||||
S_VERSION = ".".join(map(str, VERSION))
|
S_VERSION = ".".join(map(str, VERSION))
|
||||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import sys
|
|||||||
import stat
|
import stat
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from .__init__ import PY2, WINDOWS
|
from .__init__ import WINDOWS
|
||||||
from .util import IMPLICATIONS, undot, Pebkac, fsdec, fsenc, statdir, nuprint
|
from .util import IMPLICATIONS, undot, Pebkac, fsdec, fsenc, statdir, nuprint
|
||||||
|
|
||||||
|
|
||||||
@@ -96,6 +96,7 @@ class VFS(object):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def get(self, vpath, uname, will_read, will_write):
|
def get(self, vpath, uname, will_read, will_write):
|
||||||
|
# type: (str, str, bool, bool) -> tuple[VFS, str]
|
||||||
"""returns [vfsnode,fs_remainder] if user has the requested permissions"""
|
"""returns [vfsnode,fs_remainder] if user has the requested permissions"""
|
||||||
vn, rem = self._find(vpath)
|
vn, rem = self._find(vpath)
|
||||||
|
|
||||||
@@ -136,6 +137,7 @@ class VFS(object):
|
|||||||
return os.path.realpath(rp)
|
return os.path.realpath(rp)
|
||||||
|
|
||||||
def ls(self, rem, uname, scandir, incl_wo=False, lstat=False):
|
def ls(self, rem, uname, scandir, incl_wo=False, lstat=False):
|
||||||
|
# type: (str, str, bool, bool, bool) -> tuple[str, str, dict[str, VFS]]
|
||||||
"""return user-readable [fsdir,real,virt] items at vpath"""
|
"""return user-readable [fsdir,real,virt] items at vpath"""
|
||||||
virt_vis = {} # nodes readable by user
|
virt_vis = {} # nodes readable by user
|
||||||
abspath = self.canonical(rem)
|
abspath = self.canonical(rem)
|
||||||
@@ -156,13 +158,21 @@ class VFS(object):
|
|||||||
|
|
||||||
return [abspath, real, virt_vis]
|
return [abspath, real, virt_vis]
|
||||||
|
|
||||||
def walk(self, rel, rem, uname, dots, scandir, lstat=False):
|
def walk(self, rel, rem, seen, uname, dots, scandir, lstat):
|
||||||
"""
|
"""
|
||||||
recursively yields from ./rem;
|
recursively yields from ./rem;
|
||||||
rel is a unix-style user-defined vpath (not vfs-related)
|
rel is a unix-style user-defined vpath (not vfs-related)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
fsroot, vfs_ls, vfs_virt = self.ls(rem, uname, scandir, False, lstat)
|
fsroot, vfs_ls, vfs_virt = self.ls(
|
||||||
|
rem, uname, scandir, incl_wo=False, lstat=lstat
|
||||||
|
)
|
||||||
|
|
||||||
|
if seen and not fsroot.startswith(seen[-1]) and fsroot in seen:
|
||||||
|
print("bailing from symlink loop,\n {}\n {}".format(seen[-1], fsroot))
|
||||||
|
return
|
||||||
|
|
||||||
|
seen = seen[:] + [fsroot]
|
||||||
rfiles = [x for x in vfs_ls if not stat.S_ISDIR(x[1].st_mode)]
|
rfiles = [x for x in vfs_ls if not stat.S_ISDIR(x[1].st_mode)]
|
||||||
rdirs = [x for x in vfs_ls if stat.S_ISDIR(x[1].st_mode)]
|
rdirs = [x for x in vfs_ls if stat.S_ISDIR(x[1].st_mode)]
|
||||||
|
|
||||||
@@ -177,7 +187,7 @@ class VFS(object):
|
|||||||
|
|
||||||
wrel = (rel + "/" + rdir).lstrip("/")
|
wrel = (rel + "/" + rdir).lstrip("/")
|
||||||
wrem = (rem + "/" + rdir).lstrip("/")
|
wrem = (rem + "/" + rdir).lstrip("/")
|
||||||
for x in self.walk(wrel, wrem, uname, scandir, lstat):
|
for x in self.walk(wrel, wrem, seen, uname, dots, scandir, lstat):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
for n, vfs in sorted(vfs_virt.items()):
|
for n, vfs in sorted(vfs_virt.items()):
|
||||||
@@ -185,14 +195,16 @@ class VFS(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
wrel = (rel + "/" + n).lstrip("/")
|
wrel = (rel + "/" + n).lstrip("/")
|
||||||
for x in vfs.walk(wrel, "", uname, scandir, lstat):
|
for x in vfs.walk(wrel, "", seen, uname, dots, scandir, lstat):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
def zipgen(self, vrem, flt, uname, dots, scandir):
|
def zipgen(self, vrem, flt, uname, dots, scandir):
|
||||||
if flt:
|
if flt:
|
||||||
flt = {k: True for k in flt}
|
flt = {k: True for k in flt}
|
||||||
|
|
||||||
for vpath, apath, files, rd, vd in self.walk("", vrem, uname, dots, scandir):
|
for vpath, apath, files, rd, vd in self.walk(
|
||||||
|
"", vrem, [], uname, dots, scandir, False
|
||||||
|
):
|
||||||
if flt:
|
if flt:
|
||||||
files = [x for x in files if x[0] in flt]
|
files = [x for x in files if x[0] in flt]
|
||||||
|
|
||||||
@@ -616,13 +628,13 @@ class AuthSrv(object):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
atop = vn.realpath
|
atop = vn.realpath
|
||||||
g = vn.walk("", "", u, True, not self.args.no_scandir, lstat=False)
|
g = vn.walk("", "", [], u, True, not self.args.no_scandir, False)
|
||||||
for vpath, apath, files, _, _ in g:
|
for vpath, apath, files, _, _ in g:
|
||||||
fnames = [n[0] for n in files]
|
fnames = [n[0] for n in files]
|
||||||
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
vpaths = [vpath + "/" + n for n in fnames] if vpath else fnames
|
||||||
vpaths = [vtop + x for x in vpaths]
|
vpaths = [vtop + x for x in vpaths]
|
||||||
apaths = [os.path.join(apath, n) for n in fnames]
|
apaths = [os.path.join(apath, n) for n in fnames]
|
||||||
files = list(zip(vpaths, apaths))
|
files = [[vpath + "/", apath + os.sep]] + list(zip(vpaths, apaths))
|
||||||
|
|
||||||
if flag_ln:
|
if flag_ln:
|
||||||
files = [x for x in files if not x[1].startswith(atop + os.sep)]
|
files = [x for x in files if not x[1].startswith(atop + os.sep)]
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import calendar
|
|||||||
|
|
||||||
from .__init__ import E, PY2, WINDOWS, ANYWIN
|
from .__init__ import E, PY2, WINDOWS, ANYWIN
|
||||||
from .util import * # noqa # pylint: disable=unused-wildcard-import
|
from .util import * # noqa # pylint: disable=unused-wildcard-import
|
||||||
|
from .authsrv import AuthSrv
|
||||||
from .szip import StreamZip
|
from .szip import StreamZip
|
||||||
from .star import StreamTar
|
from .star import StreamTar
|
||||||
|
|
||||||
@@ -35,12 +36,12 @@ class HttpCli(object):
|
|||||||
def __init__(self, conn):
|
def __init__(self, conn):
|
||||||
self.t0 = time.time()
|
self.t0 = time.time()
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
self.s = conn.s
|
self.s = conn.s # type: socket
|
||||||
self.sr = conn.sr
|
self.sr = conn.sr # type: Unrecv
|
||||||
self.ip = conn.addr[0]
|
self.ip = conn.addr[0]
|
||||||
self.addr = conn.addr
|
self.addr = conn.addr # type: tuple[str, int]
|
||||||
self.args = conn.args
|
self.args = conn.args
|
||||||
self.auth = conn.auth
|
self.auth = conn.auth # type: AuthSrv
|
||||||
self.ico = conn.ico
|
self.ico = conn.ico
|
||||||
self.thumbcli = conn.thumbcli
|
self.thumbcli = conn.thumbcli
|
||||||
self.log_func = conn.log_func
|
self.log_func = conn.log_func
|
||||||
@@ -506,6 +507,7 @@ class HttpCli(object):
|
|||||||
items = items.replace("\r", "").split("\n")
|
items = items.replace("\r", "").split("\n")
|
||||||
items = [unquotep(x) for x in items if items]
|
items = [unquotep(x) for x in items if items]
|
||||||
|
|
||||||
|
self.parser.drop()
|
||||||
return self.tx_zip(k, v, vn, rem, items, self.args.ed)
|
return self.tx_zip(k, v, vn, rem, items, self.args.ed)
|
||||||
|
|
||||||
def handle_post_json(self):
|
def handle_post_json(self):
|
||||||
@@ -1418,7 +1420,7 @@ class HttpCli(object):
|
|||||||
try:
|
try:
|
||||||
vn, rem = self.auth.vfs.get(top, self.uname, True, False)
|
vn, rem = self.auth.vfs.get(top, self.uname, True, False)
|
||||||
fsroot, vfs_ls, vfs_virt = vn.ls(
|
fsroot, vfs_ls, vfs_virt = vn.ls(
|
||||||
rem, self.uname, not self.args.no_scandir, True
|
rem, self.uname, not self.args.no_scandir, incl_wo=True
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
vfs_ls = []
|
vfs_ls = []
|
||||||
@@ -1585,7 +1587,7 @@ class HttpCli(object):
|
|||||||
return self.tx_zip(k, v, vn, rem, [], self.args.ed)
|
return self.tx_zip(k, v, vn, rem, [], self.args.ed)
|
||||||
|
|
||||||
fsroot, vfs_ls, vfs_virt = vn.ls(
|
fsroot, vfs_ls, vfs_virt = vn.ls(
|
||||||
rem, self.uname, not self.args.no_scandir, True
|
rem, self.uname, not self.args.no_scandir, incl_wo=True
|
||||||
)
|
)
|
||||||
stats = {k: v for k, v in vfs_ls}
|
stats = {k: v for k, v in vfs_ls}
|
||||||
vfs_ls = [x[0] for x in vfs_ls]
|
vfs_ls = [x[0] for x in vfs_ls]
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ except ImportError:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
from .__init__ import E, MACOS
|
from .__init__ import E, MACOS
|
||||||
from .httpconn import HttpConn
|
|
||||||
from .authsrv import AuthSrv
|
from .authsrv import AuthSrv
|
||||||
|
from .httpconn import HttpConn
|
||||||
|
|
||||||
|
|
||||||
class HttpSrv(object):
|
class HttpSrv(object):
|
||||||
@@ -99,6 +99,7 @@ class HttpSrv(object):
|
|||||||
cli.run()
|
cli.run()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
sck = cli.s
|
||||||
if self.args.log_conn:
|
if self.args.log_conn:
|
||||||
self.log("%s %s" % addr, "|%sC-cdone" % ("-" * 7,), c="1;30")
|
self.log("%s %s" % addr, "|%sC-cdone" % ("-" * 7,), c="1;30")
|
||||||
|
|
||||||
|
|||||||
@@ -95,9 +95,11 @@ class SvcHub(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if n == 3:
|
if n == 3:
|
||||||
print("waiting for thumbsrv...")
|
print("waiting for thumbsrv (10sec)...")
|
||||||
|
|
||||||
print("nailed it")
|
print("nailed it", end="")
|
||||||
|
finally:
|
||||||
|
print("\033[0m")
|
||||||
|
|
||||||
def _log_disabled(self, src, msg, c=0):
|
def _log_disabled(self, src, msg, c=0):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -153,6 +153,9 @@ dbg.asyncStore.pendingBreakpoints = {}
|
|||||||
# fix firefox phantom breakpoints
|
# fix firefox phantom breakpoints
|
||||||
about:config >> devtools.debugger.prefs-schema-version = -1
|
about:config >> devtools.debugger.prefs-schema-version = -1
|
||||||
|
|
||||||
|
# determine server version
|
||||||
|
git reset --hard origin/HEAD && git log --format=format:"%H %ai %d" --decorate=full > /dev/shm/revs && cat /dev/shm/revs | while read -r rev extra; do (git reset --hard $rev >/dev/null 2>/dev/null && dsz=$(cat copyparty/web/{util,browser,up2k}.js 2>/dev/null | diff -wNarU0 - <(cat /mnt/Users/ed/Downloads/ref/{util,browser,up2k}.js) | wc -c) && printf '%s %6s %s\n' "$rev" $dsz "$extra") </dev/null; done
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## http 206
|
## http 206
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ grep -E '/(python|pypy)[0-9\.-]*$' >$dir/pys || true
|
|||||||
printf '\033[1;30mlooking for jinja2 in [%s]\033[0m\n' "$_py" >&2
|
printf '\033[1;30mlooking for jinja2 in [%s]\033[0m\n' "$_py" >&2
|
||||||
$_py -c 'import jinja2' 2>/dev/null || continue
|
$_py -c 'import jinja2' 2>/dev/null || continue
|
||||||
printf '%s\n' "$_py"
|
printf '%s\n' "$_py"
|
||||||
mv $dir/{,x.}jinja2
|
mv $dir/{,x.}dep-j2
|
||||||
break
|
break
|
||||||
done)"
|
done)"
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from textwrap import dedent
|
|||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
|
||||||
from tests import util as tu
|
from tests import util as tu
|
||||||
from copyparty.authsrv import AuthSrv
|
from copyparty.authsrv import AuthSrv, VFS
|
||||||
from copyparty import util
|
from copyparty import util
|
||||||
|
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ class TestVFS(unittest.TestCase):
|
|||||||
self.assertEqual(util.undot(query), response)
|
self.assertEqual(util.undot(query), response)
|
||||||
|
|
||||||
def ls(self, vfs, vpath, uname):
|
def ls(self, vfs, vpath, uname):
|
||||||
|
# type: (VFS, str, str) -> tuple[str, str, str]
|
||||||
"""helper for resolving and listing a folder"""
|
"""helper for resolving and listing a folder"""
|
||||||
vn, rem = vfs.get(vpath, uname, True, False)
|
vn, rem = vfs.get(vpath, uname, True, False)
|
||||||
r1 = vn.ls(rem, uname, False)
|
r1 = vn.ls(rem, uname, False)
|
||||||
|
|||||||
Reference in New Issue
Block a user