screengraft 0.56.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/ui.py +17 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "screengraft",
|
|
3
|
-
"version": "0.56.
|
|
3
|
+
"version": "0.56.1",
|
|
4
4
|
"description": "Put a UI screenshot or screen recording onto a photographed device screen with the perspective exactly right \u2014 a homography you confirm by hand, not a generative guess.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mockup",
|
package/scripts/ui.py
CHANGED
|
@@ -680,9 +680,10 @@ def _grain_gain(b) -> float:
|
|
|
680
680
|
"""How much of the surround's noise floor the screen carries.
|
|
681
681
|
|
|
682
682
|
The page does not set this; fresh renders get grade.SCREEN_GRAIN_GAIN. It
|
|
683
|
-
is read from the body so a
|
|
684
|
-
|
|
685
|
-
|
|
683
|
+
is read from the body so a caller that does send one (a future control, a
|
|
684
|
+
test) is honoured. Absent means the shipped gain, NOT 1.0: the API is for
|
|
685
|
+
new renders. Replaying an old sidecar is done through compose() directly,
|
|
686
|
+
where the parameter's own default (1.0) reproduces the old bytes.
|
|
686
687
|
"""
|
|
687
688
|
try:
|
|
688
689
|
g = float(b.get("grain_gain")) if b.get("grain_gain") is not None \
|
|
@@ -845,7 +846,11 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
845
846
|
if site and site not in ("same-origin", "none"):
|
|
846
847
|
return False
|
|
847
848
|
tok = self.headers.get("X-Screengraft-Token") or (q.get("t") or [""])[0]
|
|
848
|
-
|
|
849
|
+
# compare_digest wants ASCII str on both sides; a token is url-safe
|
|
850
|
+
# base64, so anything else is wrong before it is compared.
|
|
851
|
+
if not (tok and TOKEN and tok.isascii()):
|
|
852
|
+
return False
|
|
853
|
+
return secrets.compare_digest(tok, TOKEN)
|
|
849
854
|
|
|
850
855
|
def _refuse(self, u):
|
|
851
856
|
if u.path == "/":
|
|
@@ -1003,9 +1008,15 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
1003
1008
|
# Read the body off the wire first (bounded): refusing while the
|
|
1004
1009
|
# client is still sending turns a clean 403 into a broken pipe on
|
|
1005
1010
|
# its side, which reads as "the server died", not "you were refused".
|
|
1006
|
-
|
|
1011
|
+
try:
|
|
1012
|
+
n = min(int(self.headers.get("Content-Length") or 0), 64 << 20)
|
|
1013
|
+
except ValueError:
|
|
1014
|
+
n = 0
|
|
1007
1015
|
while n > 0:
|
|
1008
|
-
|
|
1016
|
+
chunk = self.rfile.read(min(n, 1 << 20))
|
|
1017
|
+
if not chunk: # client gone; nothing left to drain
|
|
1018
|
+
break
|
|
1019
|
+
n -= len(chunk)
|
|
1009
1020
|
return self._refuse(u)
|
|
1010
1021
|
try:
|
|
1011
1022
|
if u.path == "/api/upload":
|