Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f42237f2c | ||
|
|
68289cfa54 | ||
|
|
42ea30270f | ||
|
|
ebbbbf3d82 | ||
|
|
27516e2d16 | ||
|
|
84bb6f915e | ||
|
|
46752f758a | ||
|
|
34c4c22e61 | ||
|
|
af2d0b8421 | ||
|
|
638b05a49a | ||
|
|
7a13e8a7fc | ||
|
|
d9fa74711d | ||
|
|
41867f578f | ||
|
|
0bf41ed4ef |
46
README.md
46
README.md
@@ -249,13 +249,14 @@ the browser has the following hotkeys (assumes qwerty, ignores actual layout)
|
||||
* `J/L, Left/Right` prev/next file
|
||||
* `Home/End` first/last file
|
||||
* `S` toggle selection
|
||||
* `R` rotate clockwise (shift=ccw)
|
||||
* `Esc` close viewer
|
||||
* videos:
|
||||
* `U/O` skip 10sec back/forward
|
||||
* `P/K/Space` play/pause
|
||||
* `F` fullscreen
|
||||
* `C` continue playing next video
|
||||
* `R` loop
|
||||
* `V` loop
|
||||
* `M` mute
|
||||
* when the navpane is open:
|
||||
* `A/D` adjust tree width
|
||||
@@ -579,28 +580,32 @@ copyparty can invoke external programs to collect additional metadata for files
|
||||
|
||||
`ie` = internet-explorer, `ff` = firefox, `c` = chrome, `iOS` = iPhone/iPad, `Andr` = Android
|
||||
|
||||
| feature | ie6 | ie9 | ie10 | ie11 | ff 52 | c 49 | iOS | Andr |
|
||||
| --------------- | --- | --- | ---- | ---- | ----- | ---- | --- | ---- |
|
||||
| browse files | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| basic uploader | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| make directory | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| send message | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| set sort order | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| zip selection | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| navpane | - | - | `*1` | yep | yep | yep | yep | yep |
|
||||
| up2k | - | - | yep | yep | yep | yep | yep | yep |
|
||||
| markdown editor | - | - | yep | yep | yep | yep | yep | yep |
|
||||
| markdown viewer | - | - | yep | yep | yep | yep | yep | yep |
|
||||
| play mp3/m4a | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| play ogg/opus | - | - | - | - | yep | yep | `*2` | yep |
|
||||
| thumbnail view | - | - | - | - | yep | yep | yep | yep |
|
||||
| image viewer | - | - | - | - | yep | yep | yep | yep |
|
||||
| **= feature =** | ie6 | ie9 | ie10 | ie11 | ff 52 | c 49 | iOS | Andr |
|
||||
| feature | ie6 | ie9 | ie10 | ie11 | ff 52 | c 49 | iOS | Andr |
|
||||
| --------------- | --- | ---- | ---- | ---- | ----- | ---- | --- | ---- |
|
||||
| browse files | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| thumbnail view | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| basic uploader | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| up2k | - | - | `*1` | `*1` | yep | yep | yep | yep |
|
||||
| make directory | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| send message | yep | yep | yep | yep | yep | yep | yep | yep |
|
||||
| set sort order | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| zip selection | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| file rename | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| file cut/paste | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| navpane | - | `*2` | yep | yep | yep | yep | yep | yep |
|
||||
| image viewer | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| video player | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| markdown editor | - | - | yep | yep | yep | yep | yep | yep |
|
||||
| markdown viewer | - | - | yep | yep | yep | yep | yep | yep |
|
||||
| play mp3/m4a | - | yep | yep | yep | yep | yep | yep | yep |
|
||||
| play ogg/opus | - | - | - | - | yep | yep | `*3` | yep |
|
||||
| **= feature =** | ie6 | ie9 | ie10 | ie11 | ff 52 | c 49 | iOS | Andr |
|
||||
|
||||
* internet explorer 6 to 8 behave the same
|
||||
* firefox 52 and chrome 49 are the last winxp versions
|
||||
* `*1` only public folders (login session is dropped) and no history / back-button
|
||||
* `*2` using a wasm decoder which can sometimes get stuck and consumes a bit more power
|
||||
* `*1` yes, but extremely slow (ie10: 1 MiB/s, ie11: 270 KiB/s)
|
||||
* `*2` causes a full-page refresh on each navigation
|
||||
* `*3` using a wasm decoder which can sometimes get stuck and consumes a bit more power
|
||||
|
||||
quick summary of more eccentric web-browsers trying to view a directory index:
|
||||
|
||||
@@ -612,6 +617,7 @@ quick summary of more eccentric web-browsers trying to view a directory index:
|
||||
| **lynx** (2.8.9/macports) | can browse, login, upload/mkdir/msg |
|
||||
| **w3m** (0.5.3/macports) | can browse, login, upload at 100kB/s, mkdir/msg |
|
||||
| **netsurf** (3.10/arch) | is basically ie6 with much better css (javascript has almost no effect) |
|
||||
| **opera** (11.60/winxp) | OK: thumbnails, image-viewer, zip-selection, rename/cut/paste. NG: up2k, navpane, markdown, audio |
|
||||
| **ie4** and **netscape** 4.0 | can browse (text is yellow on white), upload with `?b=u` |
|
||||
| **SerenityOS** (7e98457) | hits a page fault, works with `?b=u`, file upload not-impl |
|
||||
|
||||
|
||||
@@ -378,6 +378,7 @@ def run_argparse(argv, formatter):
|
||||
ap2.add_argument("--no-thumb", action="store_true", help="disable all thumbnails")
|
||||
ap2.add_argument("--no-vthumb", action="store_true", help="disable video thumbnails")
|
||||
ap2.add_argument("--th-size", metavar="WxH", default="320x256", help="thumbnail res")
|
||||
ap2.add_argument("--th-mt", metavar="CORES", type=int, default=0, help="max num cpu cores to use, 0=all")
|
||||
ap2.add_argument("--th-no-crop", action="store_true", help="dynamic height; show full image")
|
||||
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
||||
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (0, 13, 2)
|
||||
VERSION = (0, 13, 5)
|
||||
CODENAME = "future-proof"
|
||||
BUILD_DT = (2021, 8, 12)
|
||||
BUILD_DT = (2021, 8, 16)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -956,10 +956,14 @@ class HttpCli(object):
|
||||
vfs, rem = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
||||
self._assert_safe_rem(rem)
|
||||
|
||||
upload_vpath = self.vpath
|
||||
lim = vfs.get_dbv(rem)[0].lim
|
||||
fdir_base = os.path.join(vfs.realpath, rem)
|
||||
if lim:
|
||||
fdir_base, rem = lim.all(self.ip, rem, -1, fdir_base)
|
||||
upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/")
|
||||
if not nullwrite:
|
||||
bos.makedirs(fdir_base)
|
||||
|
||||
files = []
|
||||
errmsg = ""
|
||||
@@ -986,8 +990,6 @@ class HttpCli(object):
|
||||
if lim:
|
||||
lim.chk_bup(self.ip)
|
||||
lim.chk_nup(self.ip)
|
||||
if not nullwrite:
|
||||
bos.makedirs(fdir)
|
||||
|
||||
try:
|
||||
with ren_open(fname, "wb", 512 * 1024, **open_args) as f:
|
||||
@@ -1038,7 +1040,9 @@ class HttpCli(object):
|
||||
raise
|
||||
|
||||
except Pebkac as ex:
|
||||
errmsg = volsan(self.asrv.vfs.all_vols.values(), unicode(ex))
|
||||
errmsg = vol_san(
|
||||
self.asrv.vfs.all_vols.values(), unicode(ex).encode("utf-8")
|
||||
).decode("utf-8")
|
||||
|
||||
td = max(0.1, time.time() - t0)
|
||||
sz_total = sum(x[0] for x in files)
|
||||
@@ -1058,7 +1062,7 @@ class HttpCli(object):
|
||||
errmsg = "ERROR: " + errmsg
|
||||
|
||||
for sz, sha512, ofn, lfn in files:
|
||||
vpath = (self.vpath + "/" if self.vpath else "") + lfn
|
||||
vpath = "{}/{}".format(upload_vpath, lfn).strip("/")
|
||||
msg += 'sha512: {} // {} bytes // <a href="/{}">{}</a>\n'.format(
|
||||
sha512[:56], sz, quotep(vpath), html_escape(ofn, crlf=True)
|
||||
)
|
||||
@@ -1695,7 +1699,7 @@ class HttpCli(object):
|
||||
|
||||
q = "select sz, rd, fn, at from up where ip=? and at>?"
|
||||
for sz, rd, fn, at in cur.execute(q, (self.ip, lim)):
|
||||
vp = "/" + "/".join([rd, fn]).strip("/")
|
||||
vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x)
|
||||
if filt and filt not in vp:
|
||||
continue
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ HAVE_AVIF = False
|
||||
HAVE_WEBP = False
|
||||
|
||||
try:
|
||||
from PIL import Image, ImageOps
|
||||
from PIL import Image, ImageOps, ExifTags
|
||||
|
||||
HAVE_PIL = True
|
||||
try:
|
||||
@@ -105,7 +105,10 @@ class ThumbSrv(object):
|
||||
self.mutex = threading.Lock()
|
||||
self.busy = {}
|
||||
self.stopping = False
|
||||
self.nthr = os.cpu_count() if hasattr(os, "cpu_count") else 4
|
||||
self.nthr = self.args.th_mt
|
||||
if not self.nthr:
|
||||
self.nthr = os.cpu_count() if hasattr(os, "cpu_count") else 4
|
||||
|
||||
self.q = Queue(self.nthr * 4)
|
||||
for n in range(self.nthr):
|
||||
t = threading.Thread(
|
||||
@@ -221,21 +224,38 @@ class ThumbSrv(object):
|
||||
with self.mutex:
|
||||
self.nthr -= 1
|
||||
|
||||
def fancy_pillow(self, im):
|
||||
# exif_transpose is expensive (loads full image + unconditional copy)
|
||||
r = max(*self.res) * 2
|
||||
im.thumbnail((r, r), resample=Image.LANCZOS)
|
||||
try:
|
||||
k = next(k for k, v in ExifTags.TAGS.items() if v == "Orientation")
|
||||
exif = im.getexif()
|
||||
rot = int(exif[k])
|
||||
del exif[k]
|
||||
except:
|
||||
rot = 1
|
||||
|
||||
rots = {8: Image.ROTATE_90, 3: Image.ROTATE_180, 6: Image.ROTATE_270}
|
||||
if rot in rots:
|
||||
im = im.transpose(rots[rot])
|
||||
|
||||
if self.args.th_no_crop:
|
||||
im.thumbnail(self.res, resample=Image.LANCZOS)
|
||||
else:
|
||||
iw, ih = im.size
|
||||
dw, dh = self.res
|
||||
res = (min(iw, dw), min(ih, dh))
|
||||
im = ImageOps.fit(im, res, method=Image.LANCZOS)
|
||||
|
||||
return im
|
||||
|
||||
def conv_pil(self, abspath, tpath):
|
||||
with Image.open(fsenc(abspath)) as im:
|
||||
crop = not self.args.th_no_crop
|
||||
res2 = self.res
|
||||
if crop:
|
||||
res2 = (res2[0] * 2, res2[1] * 2)
|
||||
|
||||
try:
|
||||
im.thumbnail(res2, resample=Image.LANCZOS)
|
||||
if crop:
|
||||
iw, ih = im.size
|
||||
dw, dh = self.res
|
||||
res = (min(iw, dw), min(ih, dh))
|
||||
im = ImageOps.fit(im, res, method=Image.LANCZOS)
|
||||
except:
|
||||
im = self.fancy_pillow(im)
|
||||
except Exception as ex:
|
||||
self.log("fancy_pillow {}".format(ex), "1;30")
|
||||
im.thumbnail(self.res)
|
||||
|
||||
fmts = ["RGB", "L"]
|
||||
@@ -289,6 +309,7 @@ class ThumbSrv(object):
|
||||
b"-map", b"0:v:0",
|
||||
b"-vf", scale,
|
||||
b"-frames:v", b"1",
|
||||
b"-metadata:s:v:0", b"rotate=0",
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
@@ -306,6 +327,7 @@ class ThumbSrv(object):
|
||||
]
|
||||
|
||||
cmd += [fsenc(tpath)]
|
||||
# self.log((b" ".join(cmd)).decode("utf-8"))
|
||||
|
||||
ret, sout, serr = runcmd(cmd)
|
||||
if ret != 0:
|
||||
|
||||
@@ -1223,7 +1223,8 @@ class Up2k(object):
|
||||
|
||||
self._new_upload(job)
|
||||
|
||||
purl = "/{}/".format("{}/{}".format(job["vtop"], job["prel"]).strip("/"))
|
||||
purl = "{}/{}".format(job["vtop"], job["prel"]).strip("/")
|
||||
purl = "/{}/".format(purl) if purl else "/"
|
||||
|
||||
return {
|
||||
"name": job["name"],
|
||||
|
||||
@@ -346,10 +346,8 @@ def log_thrs(log, ival, name):
|
||||
|
||||
def vol_san(vols, txt):
|
||||
for vol in vols:
|
||||
txt = txt.replace(
|
||||
vol.realpath.encode("utf-8"), vol.vpath.encode("utf-8")
|
||||
)
|
||||
|
||||
txt = txt.replace(vol.realpath.encode("utf-8"), vol.vpath.encode("utf-8"))
|
||||
|
||||
return txt
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ window.baguetteBox = (function () {
|
||||
afterHide: null,
|
||||
onChange: null,
|
||||
},
|
||||
overlay, slider, btnPrev, btnNext, btnHelp, btnSel, btnVmode, btnClose,
|
||||
overlay, slider, btnPrev, btnNext, btnHelp, btnRotL, btnRotR, btnSel, btnVmode, btnClose,
|
||||
currentGallery = [],
|
||||
currentIndex = 0,
|
||||
isOverlayVisible = false,
|
||||
@@ -49,7 +49,7 @@ window.baguetteBox = (function () {
|
||||
};
|
||||
|
||||
var touchstartHandler = function (e) {
|
||||
touch.count++;
|
||||
touch.count = e.touches.length;
|
||||
if (touch.count > 1)
|
||||
touch.multitouch = true;
|
||||
|
||||
@@ -72,8 +72,11 @@ window.baguetteBox = (function () {
|
||||
hideOverlay();
|
||||
}
|
||||
};
|
||||
var touchendHandler = function () {
|
||||
var touchendHandler = function (e) {
|
||||
touch.count--;
|
||||
if (e && e.touches)
|
||||
touch.count = e.touches.length;
|
||||
|
||||
if (touch.count <= 0)
|
||||
touch.multitouch = false;
|
||||
|
||||
@@ -175,6 +178,8 @@ window.baguetteBox = (function () {
|
||||
'<button id="bbox-next" class="bbox-btn" type="button" aria-label="Next">></button>' +
|
||||
'<div id="bbox-btns">' +
|
||||
'<button id="bbox-help" type="button">?</button>' +
|
||||
'<button id="bbox-rotl" type="button">↶</button>' +
|
||||
'<button id="bbox-rotr" type="button">↷</button>' +
|
||||
'<button id="bbox-tsel" type="button">sel</button>' +
|
||||
'<button id="bbox-vmode" type="button" tt="a"></button>' +
|
||||
'<button id="bbox-close" type="button" aria-label="Close">X</button>' +
|
||||
@@ -188,6 +193,8 @@ window.baguetteBox = (function () {
|
||||
btnPrev = ebi('bbox-prev');
|
||||
btnNext = ebi('bbox-next');
|
||||
btnHelp = ebi('bbox-help');
|
||||
btnRotL = ebi('bbox-rotl');
|
||||
btnRotR = ebi('bbox-rotr');
|
||||
btnSel = ebi('bbox-tsel');
|
||||
btnVmode = ebi('bbox-vmode');
|
||||
btnClose = ebi('bbox-close');
|
||||
@@ -205,12 +212,13 @@ window.baguetteBox = (function () {
|
||||
['right, L', 'next file'],
|
||||
['home', 'first file'],
|
||||
['end', 'last file'],
|
||||
['R', 'rotate (shift=ccw)'],
|
||||
['S', 'toggle file selection'],
|
||||
['space, P, K', 'video: play / pause'],
|
||||
['U', 'video: seek 10sec back'],
|
||||
['P', 'video: seek 10sec ahead'],
|
||||
['M', 'video: toggle mute'],
|
||||
['R', 'video: toggle loop'],
|
||||
['V', 'video: toggle loop'],
|
||||
['C', 'video: toggle auto-next'],
|
||||
['F', 'video: toggle fullscreen'],
|
||||
],
|
||||
@@ -252,7 +260,7 @@ window.baguetteBox = (function () {
|
||||
v.muted = vmute = !vmute;
|
||||
mp_ctl();
|
||||
}
|
||||
else if (k == "KeyR" && v) {
|
||||
else if (k == "KeyV" && v) {
|
||||
vloop = !vloop;
|
||||
vnext = vnext && !vloop;
|
||||
setVmode();
|
||||
@@ -272,6 +280,8 @@ window.baguetteBox = (function () {
|
||||
catch (ex) { }
|
||||
else if (k == "KeyS")
|
||||
tglsel();
|
||||
else if (k == "KeyR")
|
||||
rotn(e.shiftKey ? -1 : 1);
|
||||
}
|
||||
|
||||
function setVmode() {
|
||||
@@ -284,7 +294,7 @@ window.baguetteBox = (function () {
|
||||
if (vloop) {
|
||||
lbl = 'Loop';
|
||||
msg += 'repeat it';
|
||||
tts = '$NHotkey: R';
|
||||
tts = '$NHotkey: V';
|
||||
}
|
||||
else if (vnext) {
|
||||
lbl = 'Cont';
|
||||
@@ -333,7 +343,7 @@ window.baguetteBox = (function () {
|
||||
}
|
||||
|
||||
function selbg() {
|
||||
var img = imagesElements[currentIndex].querySelector('img, video'),
|
||||
var img = vidimg(),
|
||||
thumb = currentGallery[currentIndex].imageElement,
|
||||
name = vsplit(thumb.href)[1],
|
||||
files = msel.getsel(),
|
||||
@@ -346,11 +356,11 @@ window.baguetteBox = (function () {
|
||||
ebi('bbox-overlay').style.background = sel ?
|
||||
'rgba(153,34,85,0.7)' : '';
|
||||
|
||||
img.style.boxShadow = sel ? '0 0 3em #f4a' : '';
|
||||
img.style.borderRadius = sel ? '1em' : '';
|
||||
btnSel.style.color = sel ? '#fff' : '';
|
||||
btnSel.style.background = sel ? '#d48' : '';
|
||||
btnSel.style.textShadow = sel ? '1px 1px 0 #b38' : '';
|
||||
btnSel.style.boxShadow = sel ? '.15em .15em 0 #502' : '';
|
||||
}
|
||||
|
||||
function keyUpHandler(e) {
|
||||
@@ -387,6 +397,8 @@ window.baguetteBox = (function () {
|
||||
bind(btnClose, 'click', hideOverlay);
|
||||
bind(btnVmode, 'click', tglVmode);
|
||||
bind(btnHelp, 'click', halp);
|
||||
bind(btnRotL, 'click', rotl);
|
||||
bind(btnRotR, 'click', rotr);
|
||||
bind(btnSel, 'click', tglsel);
|
||||
bind(slider, 'contextmenu', contextmenuHandler);
|
||||
bind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
||||
@@ -402,12 +414,15 @@ window.baguetteBox = (function () {
|
||||
unbind(btnClose, 'click', hideOverlay);
|
||||
unbind(btnVmode, 'click', tglVmode);
|
||||
unbind(btnHelp, 'click', halp);
|
||||
unbind(btnRotL, 'click', rotl);
|
||||
unbind(btnRotR, 'click', rotr);
|
||||
unbind(btnSel, 'click', tglsel);
|
||||
unbind(slider, 'contextmenu', contextmenuHandler);
|
||||
unbind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
||||
unbind(overlay, 'touchmove', touchmoveHandler, passiveEvent);
|
||||
unbind(overlay, 'touchend', touchendHandler);
|
||||
unbind(document, 'focus', trapFocusInsideOverlay, true);
|
||||
timer.rm(rotn);
|
||||
}
|
||||
|
||||
function prepareOverlay(gallery, userOptions) {
|
||||
@@ -658,10 +673,91 @@ window.baguetteBox = (function () {
|
||||
return true;
|
||||
}
|
||||
|
||||
var prev_cw = 0, prev_ch = 0, unrot_timer = null;
|
||||
function rotn(n) {
|
||||
var el = vidimg(),
|
||||
orot = parseInt(el.getAttribute('rot') || 0),
|
||||
frot = orot + (n || 0) * 90;
|
||||
|
||||
if (!frot && !orot)
|
||||
return; // reflow noop
|
||||
|
||||
var co = ebi('bbox-overlay'),
|
||||
cw = co.clientWidth,
|
||||
ch = co.clientHeight;
|
||||
|
||||
if (!n && prev_cw === cw && prev_ch === ch)
|
||||
return; // reflow noop
|
||||
|
||||
prev_cw = cw;
|
||||
prev_ch = ch;
|
||||
var rot = frot,
|
||||
iw = el.naturalWidth || el.videoWidth,
|
||||
ih = el.naturalHeight || el.videoHeight,
|
||||
magic = 4, // idk, works in enough browsers
|
||||
dl = el.closest('div').querySelector('figcaption a'),
|
||||
vw = cw,
|
||||
vh = ch - dl.offsetHeight + magic,
|
||||
pmag = Math.min(1, Math.min(vw / ih, vh / iw)),
|
||||
wmag = Math.min(1, Math.min(vw / iw, vh / ih));
|
||||
|
||||
while (rot < 0) rot += 360;
|
||||
while (rot >= 360) rot -= 360;
|
||||
var q = rot == 90 || rot == 270 ? 1 : 0,
|
||||
mag = q ? pmag : wmag;
|
||||
|
||||
el.style.cssText = 'max-width:none; max-height:none; position:absolute; display:block; margin:0';
|
||||
if (!orot) {
|
||||
el.style.width = iw * wmag + 'px';
|
||||
el.style.height = ih * wmag + 'px';
|
||||
el.style.left = (vw - iw * wmag) / 2 + 'px';
|
||||
el.style.top = (vh - ih * wmag) / 2 - magic + 'px';
|
||||
q = el.offsetHeight;
|
||||
}
|
||||
el.style.width = iw * mag + 'px';
|
||||
el.style.height = ih * mag + 'px';
|
||||
el.style.left = (vw - iw * mag) / 2 + 'px';
|
||||
el.style.top = (vh - ih * mag) / 2 - magic + 'px';
|
||||
el.style.transform = 'rotate(' + frot + 'deg)';
|
||||
el.setAttribute('rot', frot);
|
||||
timer.add(rotn);
|
||||
if (!rot) {
|
||||
clearTimeout(unrot_timer);
|
||||
unrot_timer = setTimeout(unrot, 300);
|
||||
}
|
||||
}
|
||||
function rotl() {
|
||||
rotn(-1);
|
||||
}
|
||||
function rotr() {
|
||||
rotn(1);
|
||||
}
|
||||
function unrot() {
|
||||
var el = vidimg(),
|
||||
orot = el.getAttribute('rot'),
|
||||
rot = parseInt(orot || 0);
|
||||
|
||||
while (rot < 0) rot += 360;
|
||||
while (rot >= 360) rot -= 360;
|
||||
if (rot || orot === null)
|
||||
return;
|
||||
|
||||
clmod(el, 'nt', 1);
|
||||
el.removeAttribute('rot');
|
||||
el.removeAttribute("style");
|
||||
rot = el.offsetHeight;
|
||||
clmod(el, 'nt');
|
||||
timer.rm(rotn);
|
||||
}
|
||||
|
||||
function vid() {
|
||||
return imagesElements[currentIndex].querySelector('video');
|
||||
}
|
||||
|
||||
function vidimg() {
|
||||
return imagesElements[currentIndex].querySelector('img, video');
|
||||
}
|
||||
|
||||
function playvid(play) {
|
||||
if (vid())
|
||||
vid()[play ? 'play' : 'pause']();
|
||||
@@ -703,15 +799,21 @@ window.baguetteBox = (function () {
|
||||
}
|
||||
|
||||
function updateOffset() {
|
||||
var offset = -currentIndex * 100 + '%';
|
||||
var offset = -currentIndex * 100 + '%',
|
||||
xform = slider.style.perspective !== undefined;
|
||||
|
||||
if (options.animation === 'fadeIn') {
|
||||
slider.style.opacity = 0;
|
||||
setTimeout(function () {
|
||||
slider.style.transform = 'translate3d(' + offset + ',0,0)';
|
||||
xform ?
|
||||
slider.style.transform = 'translate3d(' + offset + ',0,0)' :
|
||||
slider.style.left = offset;
|
||||
slider.style.opacity = 1;
|
||||
}, 400);
|
||||
} else {
|
||||
slider.style.transform = 'translate3d(' + offset + ',0,0)';
|
||||
xform ?
|
||||
slider.style.transform = 'translate3d(' + offset + ',0,0)' :
|
||||
slider.style.left = offset;
|
||||
}
|
||||
playvid(false);
|
||||
var v = vid();
|
||||
@@ -723,6 +825,18 @@ window.baguetteBox = (function () {
|
||||
selbg();
|
||||
mp_ctl();
|
||||
setVmode();
|
||||
|
||||
var el = vidimg();
|
||||
if (el.getAttribute('rot'))
|
||||
timer.add(rotn);
|
||||
else
|
||||
timer.rm(rotn);
|
||||
|
||||
var prev = QS('.full-image.vis');
|
||||
if (prev)
|
||||
clmod(prev, 'vis');
|
||||
|
||||
clmod(el.closest('div'), 'vis', 1);
|
||||
}
|
||||
|
||||
function preloadNext(index) {
|
||||
|
||||
@@ -417,17 +417,10 @@ html.light #ggrid a.sel {
|
||||
html.light #wfm a:not(.en) {
|
||||
color: #c4a;
|
||||
}
|
||||
#files tbody tr.c1 td {
|
||||
animation: fcut1 .5s ease-out;
|
||||
#files tbody tr.fcut td {
|
||||
animation: fcut .5s ease-out;
|
||||
}
|
||||
#files tbody tr.c2 td {
|
||||
animation: fcut2 .5s ease-out;
|
||||
}
|
||||
@keyframes fcut1 {
|
||||
0% {opacity:0}
|
||||
100% {opacity:1}
|
||||
}
|
||||
@keyframes fcut2 {
|
||||
@keyframes fcut {
|
||||
0% {opacity:0}
|
||||
100% {opacity:1}
|
||||
}
|
||||
@@ -709,6 +702,10 @@ input.eq_gain {
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
height: 2.2em;
|
||||
line-height: 2.2em;
|
||||
border-bottom: 1px solid #555;
|
||||
overflow: hidden;
|
||||
}
|
||||
#thx_ff {
|
||||
padding: 5em 0;
|
||||
@@ -896,6 +893,7 @@ html.light #ghead {
|
||||
}
|
||||
#ggrid a {
|
||||
display: inline-block;
|
||||
width: 10em;
|
||||
width: var(--grid-sz);
|
||||
vertical-align: top;
|
||||
overflow-wrap: break-word;
|
||||
@@ -909,7 +907,9 @@ html.light #ghead {
|
||||
}
|
||||
#ggrid a img {
|
||||
border-radius: .2em;
|
||||
max-width: 10em;
|
||||
max-width: var(--grid-sz);
|
||||
max-height: 8em;
|
||||
max-height: calc(var(--grid-sz)/1.25);
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
@@ -1251,6 +1251,7 @@ html.light #files tr.sel a:hover {
|
||||
}
|
||||
html.light #treeh {
|
||||
background: #eee;
|
||||
border-color: #ddd;
|
||||
}
|
||||
html.light #tree {
|
||||
scrollbar-color: #a70 #ddd;
|
||||
@@ -1294,7 +1295,7 @@ html.light #tree::-webkit-scrollbar {
|
||||
opacity: 0;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
touch-action: pinch-zoom;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
@@ -1328,6 +1329,14 @@ html.light #tree::-webkit-scrollbar {
|
||||
max-height: calc(100% - 1.4em);
|
||||
margin-bottom: 1.4em;
|
||||
vertical-align: middle;
|
||||
transition: transform .23s, left .23s, top .23s, width .23s, height .23s;
|
||||
}
|
||||
.full-image img.nt,
|
||||
.full-image video.nt {
|
||||
transition: none;
|
||||
}
|
||||
.full-image.vis img,
|
||||
.full-image.vis video {
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.full-image video {
|
||||
@@ -1341,6 +1350,7 @@ html.light #tree::-webkit-scrollbar {
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
color: #ccc;
|
||||
z-index: 1;
|
||||
}
|
||||
#bbox-overlay figcaption a {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
|
||||
@@ -160,6 +160,7 @@ ebi('tree').innerHTML = (
|
||||
' <a href="#" class="btn" step="2" id="twobytwo" tt="Hotkey: A">+</a>\n' +
|
||||
' <a href="#" class="btn" step="-2" id="twig" tt="Hotkey: D">–</a>\n' +
|
||||
' <a href="#" class="tgl btn" id="dyntree" tt="autogrow as tree expands">a</a>\n' +
|
||||
' <a href="#" class="btn" id="visdir" tt="scroll to selected folder">v</a>\n' +
|
||||
'</div>\n' +
|
||||
'<ul id="treeul"></ul>\n' +
|
||||
'<div id="thx_ff"> </div>'
|
||||
@@ -1657,7 +1658,7 @@ var fileman = (function () {
|
||||
r.clip = jread('fman_clip', []);
|
||||
|
||||
var nsel = msel.getsel().length;
|
||||
clmod(bren, 'en', nsel == 1);
|
||||
clmod(bren, 'en', nsel);
|
||||
clmod(bdel, 'en', nsel);
|
||||
clmod(bcut, 'en', nsel);
|
||||
clmod(bpst, 'en', r.clip && r.clip.length);
|
||||
@@ -2018,17 +2019,21 @@ var fileman = (function () {
|
||||
if (!sel.length)
|
||||
return toast.err(3, 'select at least 1 item to cut');
|
||||
|
||||
if (sel.length < 100)
|
||||
for (var a = 0; a < sel.length; a++) {
|
||||
vps.push(sel[a].vp);
|
||||
var cl = ebi(sel[a].id).closest('tr').classList,
|
||||
inv = cl.contains('c1');
|
||||
|
||||
cl.remove(inv ? 'c1' : 'c2');
|
||||
cl.add(inv ? 'c2' : 'c1');
|
||||
var els = [];
|
||||
for (var a = 0; a < sel.length; a++) {
|
||||
vps.push(sel[a].vp);
|
||||
if (sel.length < 100) {
|
||||
els.push(ebi(sel[a].id).closest('tr'));
|
||||
clmod(els[a], 'fcut');
|
||||
}
|
||||
}
|
||||
|
||||
toast.inf(1, 'cut ' + sel.length + ' items');
|
||||
setTimeout(function () {
|
||||
for (var a = 0; a < els.length; a++)
|
||||
clmod(els[a], 'fcut', 1);
|
||||
}, 1);
|
||||
|
||||
toast.inf(1.5, 'cut ' + sel.length + ' items');
|
||||
jwrite('fman_clip', vps);
|
||||
r.tx(1);
|
||||
};
|
||||
@@ -2391,7 +2396,8 @@ var thegrid = (function () {
|
||||
})();
|
||||
|
||||
|
||||
function tree_scrollto() {
|
||||
function tree_scrollto(e) {
|
||||
ev(e);
|
||||
var act = QS('#treeul a.hl'),
|
||||
ul = act ? act.offsetParent : null;
|
||||
|
||||
@@ -2851,7 +2857,7 @@ var treectl = (function () {
|
||||
var treectl = {
|
||||
"hidden": true,
|
||||
"ls_cb": null,
|
||||
"dir_cb": null
|
||||
"dir_cb": tree_scrollto
|
||||
},
|
||||
entreed = false,
|
||||
fixedpos = false,
|
||||
@@ -3155,7 +3161,13 @@ var treectl = (function () {
|
||||
}
|
||||
html.push('</tbody>');
|
||||
html = html.join('\n');
|
||||
ebi('files').innerHTML = html;
|
||||
try {
|
||||
ebi('files').innerHTML = html;
|
||||
}
|
||||
catch (ex) { //ie9
|
||||
window.location.href = this.top;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hpush)
|
||||
hist_push(this.top);
|
||||
@@ -3239,6 +3251,7 @@ var treectl = (function () {
|
||||
|
||||
ebi('entree').onclick = treectl.entree;
|
||||
ebi('detree').onclick = treectl.detree;
|
||||
ebi('visdir').onclick = tree_scrollto;
|
||||
ebi('dotfiles').onclick = tdots;
|
||||
ebi('dyntree').onclick = dyntree;
|
||||
ebi('twig').onclick = scaletree;
|
||||
@@ -3775,7 +3788,7 @@ var msel = (function () {
|
||||
if (r.all && r.all.length) {
|
||||
for (var a = 0; a < r.all.length; a++) {
|
||||
var ao = r.all[a];
|
||||
ao.sel = ebi(ao.id).closest('tr').classList.contains('sel');
|
||||
ao.sel = clgot(ebi(ao.id).closest('tr'), 'sel');
|
||||
if (ao.sel)
|
||||
r.sel.push(ao);
|
||||
}
|
||||
@@ -3791,7 +3804,7 @@ var msel = (function () {
|
||||
item = {};
|
||||
|
||||
item.id = links[a].getAttribute('id');
|
||||
item.sel = links[a].closest('tr').classList.contains('sel');
|
||||
item.sel = clgot(links[a].closest('tr'), 'sel');
|
||||
item.vp = href.indexOf('/') !== -1 ? href : vbase + href;
|
||||
|
||||
r.all.push(item);
|
||||
|
||||
@@ -370,8 +370,8 @@ function save_cb() {
|
||||
}
|
||||
|
||||
if (!r.ok) {
|
||||
if (!this.btn.classList.contains('force-save')) {
|
||||
this.btn.classList.add('force-save');
|
||||
if (!clgot(this.btn, 'force-save')) {
|
||||
clmod(this.btn, 'force-save', 1);
|
||||
var msg = [
|
||||
'This file has been modified since you started editing it!\n',
|
||||
'if you really want to overwrite, press save again.\n',
|
||||
@@ -387,7 +387,7 @@ function save_cb() {
|
||||
return toast.err(0, 'Error! Save failed. Maybe this JSON explains why:\n\n' + this.responseText);
|
||||
}
|
||||
|
||||
this.btn.classList.remove('force-save');
|
||||
clmod(this.btn, 'force-save');
|
||||
//alert('save OK -- wrote ' + r.size + ' bytes.\n\nsha512: ' + r.sha512);
|
||||
|
||||
run_savechk(r.lastmod, this.txt, this.btn, 0);
|
||||
|
||||
@@ -96,20 +96,16 @@ function md_changed(mde, on_srv) {
|
||||
var md_now = mde.value();
|
||||
var save_btn = QS('.editor-toolbar button.save');
|
||||
|
||||
if (md_now == window.md_saved)
|
||||
save_btn.classList.add('disabled');
|
||||
else
|
||||
save_btn.classList.remove('disabled');
|
||||
|
||||
clmod(save_btn, 'disabled', md_now == window.md_saved);
|
||||
set_jumpto();
|
||||
}
|
||||
|
||||
function save(mde) {
|
||||
var save_btn = QS('.editor-toolbar button.save');
|
||||
if (save_btn.classList.contains('disabled'))
|
||||
if (clgot(save_btn, 'disabled'))
|
||||
return toast.inf(2, 'no changes');
|
||||
|
||||
var force = save_btn.classList.contains('force-save');
|
||||
var force = clgot(save_btn, 'force-save');
|
||||
function save2() {
|
||||
var txt = mde.value();
|
||||
|
||||
@@ -153,8 +149,8 @@ function save_cb() {
|
||||
}
|
||||
|
||||
if (!r.ok) {
|
||||
if (!this.btn.classList.contains('force-save')) {
|
||||
this.btn.classList.add('force-save');
|
||||
if (!clgot(this.btn, 'force-save')) {
|
||||
clmod(this.btn, 'force-save', 1);
|
||||
var msg = [
|
||||
'This file has been modified since you started editing it!\n',
|
||||
'if you really want to overwrite, press save again.\n',
|
||||
@@ -170,7 +166,7 @@ function save_cb() {
|
||||
return toast.err(0, 'Error! Save failed. Maybe this JSON explains why:\n\n' + this.responseText);
|
||||
}
|
||||
|
||||
this.btn.classList.remove('force-save');
|
||||
clmod(this.btn, 'force-save');
|
||||
//alert('save OK -- wrote ' + r.size + ' bytes.\n\nsha512: ' + r.sha512);
|
||||
|
||||
// download the saved doc from the server and compare
|
||||
|
||||
@@ -511,7 +511,7 @@ function up2k_init(subtle) {
|
||||
import_js('/.cpr/deps/' + fn, unmodal);
|
||||
|
||||
if (is_https)
|
||||
ebi('u2foot').innerHTML = shame + ' so <em>this</em> uploader will do like 500kB/s at best';
|
||||
ebi('u2foot').innerHTML = shame + ' so <em>this</em> uploader will do like 500 KiB/s at best';
|
||||
else
|
||||
ebi('u2foot').innerHTML = 'seems like ' + shame + ' so do that if you want more performance <span style="color:#' +
|
||||
(sha_js == 'ac' ? 'c84">(expecting 20' : '8a5">(but dont worry too much, expect 100') + ' MiB/s)</span>';
|
||||
@@ -805,13 +805,13 @@ function up2k_init(subtle) {
|
||||
for (var a = 0; a < good_files.length; a++) {
|
||||
var fobj = good_files[a][0],
|
||||
name = good_files[a][1],
|
||||
fdir = '',
|
||||
fdir = get_evpath(),
|
||||
now = Date.now(),
|
||||
lmod = fobj.lastModified || now,
|
||||
ofs = name.lastIndexOf('/') + 1;
|
||||
|
||||
if (ofs) {
|
||||
fdir = name.slice(0, ofs);
|
||||
fdir += url_enc(name.slice(0, ofs));
|
||||
name = name.slice(ofs);
|
||||
}
|
||||
|
||||
@@ -1263,7 +1263,7 @@ function up2k_init(subtle) {
|
||||
try { orz(e); } catch (ex) { vis_exh(ex + '', '', '', '', ex); }
|
||||
};
|
||||
|
||||
xhr.open('HEAD', t.purl + t.name, true);
|
||||
xhr.open('HEAD', t.purl + uricom_enc(t.name), true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
@@ -1340,12 +1340,13 @@ function up2k_init(subtle) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.purl !== t.purl || response.name !== t.name) {
|
||||
var rsp_purl = url_enc(response.purl);
|
||||
if (rsp_purl !== t.purl || response.name !== t.name) {
|
||||
// server renamed us (file exists / path restrictions)
|
||||
console.log("server-rename [" + t.purl + "] [" + t.name + "] to [" + response.purl + "] [" + response.name + "]");
|
||||
t.purl = response.purl;
|
||||
console.log("server-rename [" + t.purl + "] [" + t.name + "] to [" + rsp_purl + "] [" + response.name + "]");
|
||||
t.purl = rsp_purl;
|
||||
t.name = response.name;
|
||||
pvis.seth(t.n, 0, linksplit(t.purl + t.name).join(' '));
|
||||
pvis.seth(t.n, 0, linksplit(uricom_dec(t.purl)[0] + t.name).join(' '));
|
||||
}
|
||||
|
||||
var chunksize = get_chunksize(t.size),
|
||||
@@ -1703,11 +1704,10 @@ function up2k_init(subtle) {
|
||||
catch (ex) { }
|
||||
|
||||
try {
|
||||
var fun = fsearch ? 'add' : 'remove',
|
||||
ico = fsearch ? '🔎' : '🚀',
|
||||
var ico = fsearch ? '🔎' : '🚀',
|
||||
desc = fsearch ? 'Search' : 'Upload';
|
||||
|
||||
ebi('op_up2k').classList[fun]('srch');
|
||||
clmod(ebi('op_up2k'), 'srch', fsearch);
|
||||
ebi('u2bm').innerHTML = ico + ' <sup>' + desc + '</sup>';
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
@@ -123,11 +123,18 @@ if (!String.startsWith) {
|
||||
return this.substring(i, i + s.length) === s;
|
||||
};
|
||||
}
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches =
|
||||
Element.prototype.oMatchesSelector ||
|
||||
Element.prototype.msMatchesSelector ||
|
||||
Element.prototype.mozMatchesSelector ||
|
||||
Element.prototype.webkitMatchesSelector;
|
||||
}
|
||||
if (!Element.prototype.closest) {
|
||||
Element.prototype.closest = function (s) {
|
||||
var el = this;
|
||||
do {
|
||||
if (el.msMatchesSelector(s)) return el;
|
||||
if (el.matches(s)) return el;
|
||||
el = el.parentElement || el.parentNode;
|
||||
} while (el !== null && el.nodeType === 1);
|
||||
}
|
||||
@@ -170,12 +177,28 @@ function crc32(str) {
|
||||
}
|
||||
|
||||
|
||||
function clmod(obj, cls, add) {
|
||||
function clmod(el, cls, add) {
|
||||
if (el.classList) {
|
||||
if (add == 't')
|
||||
add = el.classList.contains(cls) ? 0 : 1;
|
||||
|
||||
return el.classList[add ? 'add' : 'remove'](cls);
|
||||
}
|
||||
|
||||
var re = new RegExp('\\s*\\b' + cls + '\\s*\\b', 'g');
|
||||
if (add == 't')
|
||||
add = !re.test(obj.className);
|
||||
add = !re.test(el.className);
|
||||
|
||||
obj.className = obj.className.replace(re, ' ') + (add ? ' ' + cls : '');
|
||||
el.className = el.className.replace(re, ' ') + (add ? ' ' + cls : '');
|
||||
}
|
||||
|
||||
|
||||
function clgot(el, cls) {
|
||||
if (el.classList)
|
||||
return el.classList.contains(cls);
|
||||
|
||||
var lst = (el.getAttribute('class') + '').split(/ /g);
|
||||
return has(lst, cls);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,6 +331,16 @@ function uricom_enc(txt, do_fb_enc) {
|
||||
}
|
||||
}
|
||||
|
||||
function url_enc(txt) {
|
||||
var parts = txt.split('/'),
|
||||
ret = [];
|
||||
|
||||
for (var a = 0; a < parts.length; a++)
|
||||
ret.push(uricom_enc(parts[a]));
|
||||
|
||||
return ret.join('/');
|
||||
}
|
||||
|
||||
|
||||
function uricom_dec(txt) {
|
||||
try {
|
||||
@@ -494,7 +527,7 @@ var timer = (function () {
|
||||
apop(r.q, fun);
|
||||
};
|
||||
|
||||
function impl() {
|
||||
function doevents() {
|
||||
if (Date.now() - r.last < 69)
|
||||
return;
|
||||
|
||||
@@ -504,7 +537,7 @@ var timer = (function () {
|
||||
|
||||
r.last = Date.now();
|
||||
}
|
||||
setInterval(impl, 100);
|
||||
setInterval(doevents, 100);
|
||||
|
||||
return r;
|
||||
})();
|
||||
@@ -775,3 +808,14 @@ var modal = (function () {
|
||||
|
||||
return r;
|
||||
})();
|
||||
|
||||
|
||||
function winpopup(txt) {
|
||||
fetch(get_evpath(), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: 'msg=' + uricom_enc(Date.now() + ', ' + txt)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ about:config >> devtools.debugger.prefs-schema-version = -1
|
||||
git pull; git reset --hard origin/HEAD && git log --format=format:"%H %ai %d" --decorate=full > ../revs && cat ../{util,browser,up2k}.js >../vr && cat ../revs | while read -r rev extra; do (git reset --hard $rev >/dev/null 2>/dev/null && dsz=$(cat copyparty/web/{util,browser,up2k}.js >../vg 2>/dev/null && diff -wNarU0 ../{vg,vr} | wc -c) && printf '%s %6s %s\n' "$rev" $dsz "$extra") </dev/null; done
|
||||
|
||||
# download all sfx versions
|
||||
curl https://api.github.com/repos/9001/copyparty/releases?per_page=100 | jq -r '.[] | .tag_name + " " + .name' | while read v t; do fn="copyparty $v $t.py"; [ -e $fn ] || curl https://github.com/9001/copyparty/releases/download/$v/copyparty-sfx.py -Lo "$fn"; done
|
||||
curl https://api.github.com/repos/9001/copyparty/releases?per_page=100 | jq -r '.[] | .tag_name + " " + .name' | tr -d '\r' | while read v t; do fn="copyparty $v $t.py"; [ -e "$fn" ] || curl https://github.com/9001/copyparty/releases/download/$v/copyparty-sfx.py -Lo "$fn"; done
|
||||
|
||||
|
||||
##
|
||||
|
||||
@@ -108,6 +108,7 @@ def tc1():
|
||||
pdirs = [x.replace("\\", "/") for x in pdirs]
|
||||
udirs = [x.split("/", 2)[2] for x in pdirs]
|
||||
perms = [x.rstrip("j/")[-1] for x in pdirs]
|
||||
perms = ["rw" if x == "a" else x for x in perms]
|
||||
for pd, ud, p in zip(pdirs, udirs, perms):
|
||||
if ud[-1] == "j":
|
||||
continue
|
||||
@@ -147,14 +148,14 @@ def tc1():
|
||||
u = "{}{}/a.h264".format(ub, d)
|
||||
r = requests.get(u)
|
||||
ok = bool(r)
|
||||
if ok != (p in ["a"]):
|
||||
if ok != (p in ["rw"]):
|
||||
raise Exception("get {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
# stat filesystem
|
||||
for d, p in zip(pdirs, perms):
|
||||
u = "{}/a.h264".format(d)
|
||||
ok = os.path.exists(u)
|
||||
if ok != (p in ["a", "w"]):
|
||||
if ok != (p in ["rw", "w"]):
|
||||
raise Exception("stat {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
# GET thumbnail, vreify contents
|
||||
@@ -162,7 +163,7 @@ def tc1():
|
||||
u = "{}{}/a.h264?th=j".format(ub, d)
|
||||
r = requests.get(u)
|
||||
ok = bool(r and r.content[:3] == b"\xff\xd8\xff")
|
||||
if ok != (p in ["a"]):
|
||||
if ok != (p in ["rw"]):
|
||||
raise Exception("thumb {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
# check tags
|
||||
@@ -179,10 +180,10 @@ def tc1():
|
||||
r_ok = bool(j)
|
||||
w_ok = bool(r_ok and j.get("files"))
|
||||
|
||||
if not r_ok or w_ok != (p in ["a"]):
|
||||
if not r_ok or w_ok != (p in ["rw"]):
|
||||
raise Exception("ls {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
if (tag and p != "a") or (not tag and p == "a"):
|
||||
if (tag and p != "rw") or (not tag and p == "rw"):
|
||||
raise Exception("tag {} with perm {} at {}".format(tag, p, u))
|
||||
|
||||
if tag is not None and tag != "48x32":
|
||||
|
||||
Reference in New Issue
Block a user