Skip to content

Commit

Permalink
support mojibake and py3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
9001 committed Jun 12, 2019
1 parent bf95527 commit 63e089a
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 121 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

turn your phone or raspi into a portable file server with resumable uploads/downloads using IE6 or any other browser

* server runs on anything with `py2.7` or `py3.3+`
* server runs on anything with `py2.7` or `py3.2+`
* *resumable* uploads need `firefox 12+` / `chrome 6+` / `safari 6+` / `IE 10+`
* code standard: `black`

Expand All @@ -31,7 +31,7 @@ summary: it works
# dependencies

* `jinja2`
* pulls in `markupsafe`
* pulls in `markupsafe` as of v2.7; use jinja 2.6 on py3.2

optional, enables thumbnails:
* `Pillow` (requires py2.7 or py3.5+)
Expand Down
2 changes: 1 addition & 1 deletion copyparty/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import platform
import sys
Expand Down
2 changes: 1 addition & 1 deletion copyparty/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

"""copyparty: http file sharing hub (py2/py3)"""
__author__ = "ed <[email protected]>"
Expand Down
12 changes: 6 additions & 6 deletions copyparty/authsrv.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import os
import threading

from .__init__ import PY2
from .util import undot, Pebkac
from .util import undot, Pebkac, fsdec, fsenc


class VFS(object):
Expand Down Expand Up @@ -90,12 +90,12 @@ def canonical(self, rem):
if rem:
rp += "/" + rem

return os.path.realpath(rp)
return fsdec(os.path.realpath(fsenc(rp)))

def ls(self, rem, uname):
"""return user-readable [fsdir,real,virt] items at vpath"""
abspath = self.canonical(rem)
real = os.listdir(abspath)
real = [fsdec(x) for x in os.listdir(fsenc(abspath))]
real.sort()
if rem:
virt_vis = []
Expand Down Expand Up @@ -182,7 +182,7 @@ def _parse_config_file(self, fd, user, mread, mwrite, mount):
raise Exception('invalid mountpoint "{}"'.format(vol_dst))

# cfg files override arguments and previous files
vol_src = os.path.abspath(vol_src)
vol_src = fsdec(os.path.abspath(fsenc(vol_src)))
vol_dst = vol_dst.strip("/")
mount[vol_dst] = vol_src
mread[vol_dst] = []
Expand Down Expand Up @@ -217,7 +217,7 @@ def reload(self):
# list of src:dst:permset:permset:...
# permset is [rwa]username
for src, dst, perms in [x.split(":", 2) for x in self.args.v]:
src = os.path.abspath(src)
src = fsdec(os.path.abspath(fsenc(src)))
dst = dst.strip("/")
mount[dst] = src
mread[dst] = []
Expand Down
73 changes: 30 additions & 43 deletions copyparty/httpcli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import os
import stat
Expand All @@ -14,11 +14,6 @@

if not PY2:
unicode = str
from urllib.parse import unquote_plus
from urllib.parse import quote_plus
else:
from urllib import unquote_plus # pylint: disable=no-name-in-module
from urllib import quote_plus


class HttpCli(object):
Expand Down Expand Up @@ -76,8 +71,6 @@ def run(self):
if self.uname:
self.rvol = self.auth.vfs.user_tree(self.uname, readable=True)
self.wvol = self.auth.vfs.user_tree(self.uname, writable=True)
self.log(self.rvol)
self.log(self.wvol)

# split req into vpath + uparam
uparam = {}
Expand All @@ -100,15 +93,15 @@ def run(self):
uparam[k.lower()] = True

self.uparam = uparam
self.vpath = unquote_plus(vpath)
self.vpath = unquotep(vpath)

try:
if mode == "GET":
self.handle_get()
elif mode == "POST":
self.handle_post()
else:
self.loud_reply(u'invalid HTTP mode "{0}"'.format(mode))
self.loud_reply('invalid HTTP mode "{0}"'.format(mode))

except Pebkac as ex:
self.loud_reply(str(ex))
Expand All @@ -119,16 +112,16 @@ def run(self):
def reply(self, body, status="200 OK", mime="text/html", headers=[]):
# TODO something to reply with user-supplied values safely
response = [
u"HTTP/1.1 " + status,
u"Connection: Keep-Alive",
u"Content-Type: " + mime,
u"Content-Length: " + str(len(body)),
"HTTP/1.1 " + status,
"Connection: Keep-Alive",
"Content-Type: " + mime,
"Content-Length: " + str(len(body)),
]
for k, v in self.out_headers.items():
response.append("{}: {}".format(k, v))

response.extend(headers)
response_str = u"\r\n".join(response).encode("utf-8")
response_str = "\r\n".join(response).encode("utf-8")
if self.ok:
self.s.send(response_str + b"\r\n\r\n" + body)

Expand All @@ -143,7 +136,7 @@ def handle_get(self):
self.log("GET " + self.req)

# "embedded" resources
if self.vpath.startswith(u".cpr"):
if self.vpath.startswith(".cpr"):
static_path = os.path.join(E.mod, "web/", self.vpath[5:])

if os.path.isfile(static_path):
Expand Down Expand Up @@ -193,11 +186,11 @@ def handle_post(self):

act = self.parser.require("act", 64)

if act == u"bput":
if act == "bput":
self.handle_plain_upload()
return

if act == u"login":
if act == "login":
self.handle_login()
return

Expand All @@ -208,10 +201,10 @@ def handle_login(self):
self.parser.drop()

if pwd in self.auth.iuser:
msg = u"login ok"
msg = "login ok"
else:
msg = u"naw dude"
pwd = u"x" # nosec
msg = "naw dude"
pwd = "x" # nosec

h = ["Set-Cookie: cppwd={}; Path=/".format(pwd)]
html = self.conn.tpl_msg.render(h1=msg, h2='<a href="/">ack</a>', redir="/")
Expand All @@ -235,7 +228,7 @@ def handle_plain_upload(self):

# TODO broker which avoid this race
# and provides a new filename if taken
if os.path.exists(fn):
if os.path.exists(fsenc(fn)):
fn += ".{:.6f}".format(time.time())

with open(fn, "wb") as f:
Expand All @@ -254,10 +247,10 @@ def handle_plain_upload(self):
if not self.ok:
status = "ERROR"

msg = u"{0} // {1} bytes // {2:.3f} MiB/s\n".format(status, sz_total, spd)
msg = "{0} // {1} bytes // {2:.3f} MiB/s\n".format(status, sz_total, spd)

for sz, sha512 in files:
msg += u"sha512: {0} // {1} bytes\n".format(sha512[:56], sz)
msg += "sha512: {0} // {1} bytes\n".format(sha512[:56], sz)
# truncated SHA-512 prevents length extension attacks;
# using SHA-512/224, optionally SHA-512/256 = :64

Expand All @@ -276,10 +269,10 @@ def handle_plain_upload(self):
with open(log_fn, "wb") as f:
f.write(
(
u"\n".join(
"\n".join(
unicode(x)
for x in [
u":".join(unicode(x) for x in self.addr),
":".join(unicode(x) for x in self.addr),
msg.rstrip(),
]
)
Expand All @@ -288,7 +281,7 @@ def handle_plain_upload(self):
)

def tx_file(self, path):
sz = os.path.getsize(path)
sz = os.path.getsize(fsenc(path))
mime = mimetypes.guess_type(path)[0]
header = "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: {}\r\nContent-Length: {}\r\n\r\n".format(
mime, sz
Expand All @@ -299,7 +292,7 @@ def tx_file(self, path):
if self.ok:
self.s.send(header)

with open(path, "rb") as f:
with open(fsenc(path), "rb") as f:
while self.ok:
buf = f.read(4096)
if not buf:
Expand All @@ -321,20 +314,20 @@ def tx_upper(self):
self.loud_reply("TODO jupper {}".format(self.vpath))

def tx_browser(self):
vpath = u""
vpnodes = [[u"/", u"/"]]
vpath = ""
vpnodes = [["/", "/"]]
for node in self.vpath.split("/"):
vpath += u"/" + node
vpnodes.append([quote_plus(vpath, safe="/") + "/", cgi.escape(node)])
vpath += "/" + node
vpnodes.append([quotep(vpath) + "/", cgi.escape(node)])

vn, rem = self.auth.vfs.get(self.vpath, self.uname, True, False)
abspath = vn.canonical(rem)

if not os.path.exists(abspath):
if not os.path.exists(fsenc(abspath)):
print(abspath)
raise Pebkac("404 not found")

if not os.path.isdir(abspath):
if not os.path.isdir(fsenc(abspath)):
return self.tx_file(abspath)

fsroot, vfs_ls, vfs_virt = vn.ls(rem, self.uname)
Expand All @@ -348,7 +341,7 @@ def tx_browser(self):
href = vpath + "/" + fn

fspath = fsroot + "/" + fn
inf = os.stat(fspath)
inf = os.stat(fsenc(fspath))

is_dir = stat.S_ISDIR(inf.st_mode)
if is_dir:
Expand All @@ -361,13 +354,7 @@ def tx_browser(self):
dt = datetime.utcfromtimestamp(inf.st_mtime)
dt = dt.strftime("%Y-%m-%d %H:%M:%S")

item = [
margin,
quote_plus(href, safe="/"),
cgi.escape(fn, quote=True),
sz,
dt,
]
item = [margin, quotep(href), cgi.escape(fn, quote=True), sz, dt]
if is_dir:
dirs.append(item)
else:
Expand All @@ -377,4 +364,4 @@ def tx_browser(self):
html = self.conn.tpl_browser.render(
vpnodes=vpnodes, files=dirs, can_upload=self.writable
)
self.reply(html.encode("utf-8"))
self.reply(html.encode("utf-8", "replace"))
2 changes: 1 addition & 1 deletion copyparty/httpconn.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import os
import jinja2
Expand Down
2 changes: 1 addition & 1 deletion copyparty/httpsrv.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import time
import threading
Expand Down
2 changes: 1 addition & 1 deletion copyparty/mpsrv.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals

import sys
import time
Expand Down
2 changes: 1 addition & 1 deletion copyparty/msgsvc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
from __future__ import print_function, unicode_literals


class MsgSvc(object):
Expand Down
Loading

0 comments on commit 63e089a

Please sign in to comment.