Skip to content

Commit

Permalink
test + fix path jumps
Browse files Browse the repository at this point in the history
  • Loading branch information
pegasko committed Jan 8, 2024
1 parent b87e95e commit fdccf5f
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 65 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
venv/*
test/*
*/__pycache__/*
*.egg-info
build/*
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ web-based remote file manager
# What is it?

Xleb is a single-module python utility used to browse and manage files on rempote host with support of:
* File upload/download
* File upload/download including drap & drop
* File delete
* File move/rename
* File listing
Expand All @@ -33,7 +33,7 @@ or directly

```
$ xleb -h
usage: xleb [-h] [--path PATH] [--port PORT] [--host HOST] [--log-level LOG_LEVEL] [--log] [--password PASSWORD]
usage: xleb [-h] [--path PATH] [--port PORT] [--host HOST] [--log-level LOG_LEVEL] [--log] [--password PASSWORD] [--origins ORIGINS [ORIGINS ...]]
options:
-h, --help show this help message and exit
Expand All @@ -45,8 +45,17 @@ options:
--log, -l enable logging
--password PASSWORD, -s PASSWORD
user password
--origins ORIGINS [ORIGINS ...], -r ORIGINS [ORIGINS ...]
allowed origins for cors. by default allows all
```

# Notes

* password is sent and stored inside cookie without hashing due to lack of built-in hashing algorightms in vanilla javascript
* password (from cookie) is used as auth for every action
* by default CORS allows everything
* if file exists during upload, it is ignored and untouched on server

# LICENSE

```
Expand Down
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
testpaths = test
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='xleb',
version='1.3',
version='1.4',
py_modules=['xleb'],
packages=['xleb'],
description='web-based remote file manager',
Expand Down
Empty file added test/__init__.py
Empty file.
105 changes: 105 additions & 0 deletions test/test_pathutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import xleb.pathutils

from xleb.config import config


def test_normalize_abs_posixpath():
"""Test pathutils webpath normalization"""

assert xleb.pathutils.normalize_abs_posixpath('') == '/'
assert xleb.pathutils.normalize_abs_posixpath('/') == '/'

assert xleb.pathutils.normalize_abs_posixpath(' ') == '/'
assert xleb.pathutils.normalize_abs_posixpath(' / ') == '/'
assert xleb.pathutils.normalize_abs_posixpath(' //// ') == '/'
assert xleb.pathutils.normalize_abs_posixpath('///////') == '/'
assert xleb.pathutils.normalize_abs_posixpath('/ / / /') == '/'
assert xleb.pathutils.normalize_abs_posixpath(' // / ') == '/'
assert xleb.pathutils.normalize_abs_posixpath('///////foo') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('/// ///foo') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('///////foo/') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('//// / foo/') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath(' foo/') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath(' foo ') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('/foo/////') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('///////foo////') == '/foo'

assert xleb.pathutils.normalize_abs_posixpath('foo') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('/foo') == '/foo'

assert xleb.pathutils.normalize_abs_posixpath('foo/bar') == '/foo/bar'
assert xleb.pathutils.normalize_abs_posixpath('/foo/bar') == '/foo/bar'

assert xleb.pathutils.normalize_abs_posixpath('foo/../bar') == '/bar'
assert xleb.pathutils.normalize_abs_posixpath('/foo/../bar') == '/bar'

assert xleb.pathutils.normalize_abs_posixpath('..') == '/'
assert xleb.pathutils.normalize_abs_posixpath('/..') == '/'

assert xleb.pathutils.normalize_abs_posixpath('../foo') == '/foo'
assert xleb.pathutils.normalize_abs_posixpath('/../foo') == '/foo'


def test_posixpath_to_fspath():
"""Test pathutils webpath to fspath"""

rootpath = '/foo/bar'

assert xleb.pathutils.posixpath_to_fspath('', rootpath=rootpath) == '/foo/bar'
assert xleb.pathutils.posixpath_to_fspath('/', rootpath=rootpath) == '/foo/bar'

assert xleb.pathutils.posixpath_to_fspath('baz', rootpath=rootpath) == '/foo/bar/baz'
assert xleb.pathutils.posixpath_to_fspath('/baz', rootpath=rootpath) == '/foo/bar/baz'

assert xleb.pathutils.posixpath_to_fspath('baz/taz', rootpath=rootpath) == '/foo/bar/baz/taz'
assert xleb.pathutils.posixpath_to_fspath('/baz/taz', rootpath=rootpath) == '/foo/bar/baz/taz'

assert xleb.pathutils.posixpath_to_fspath('baz/../taz', rootpath=rootpath) == '/foo/bar/taz'
assert xleb.pathutils.posixpath_to_fspath('/baz/../taz', rootpath=rootpath) == '/foo/bar/taz'

assert xleb.pathutils.posixpath_to_fspath('..', rootpath=rootpath) == '/foo/bar'
assert xleb.pathutils.posixpath_to_fspath('/..', rootpath=rootpath) == '/foo/bar'

assert xleb.pathutils.posixpath_to_fspath('../taz', rootpath=rootpath) == '/foo/bar/taz'
assert xleb.pathutils.posixpath_to_fspath('/../taz', rootpath=rootpath) == '/foo/bar/taz'

rootpath = '/foo/bar/'

assert xleb.pathutils.posixpath_to_fspath('', rootpath=rootpath) == '/foo/bar'
assert xleb.pathutils.posixpath_to_fspath('/', rootpath=rootpath) == '/foo/bar'

assert xleb.pathutils.posixpath_to_fspath('baz', rootpath=rootpath) == '/foo/bar/baz'
assert xleb.pathutils.posixpath_to_fspath('/baz', rootpath=rootpath) == '/foo/bar/baz'

assert xleb.pathutils.posixpath_to_fspath('baz/taz', rootpath=rootpath) == '/foo/bar/baz/taz'
assert xleb.pathutils.posixpath_to_fspath('/baz/taz', rootpath=rootpath) == '/foo/bar/baz/taz'

assert xleb.pathutils.posixpath_to_fspath('baz/../taz', rootpath=rootpath) == '/foo/bar/taz'
assert xleb.pathutils.posixpath_to_fspath('/baz/../taz', rootpath=rootpath) == '/foo/bar/taz'

assert xleb.pathutils.posixpath_to_fspath('..', rootpath=rootpath) == '/foo/bar'
assert xleb.pathutils.posixpath_to_fspath('/..', rootpath=rootpath) == '/foo/bar'

assert xleb.pathutils.posixpath_to_fspath('../taz', rootpath=rootpath) == '/foo/bar/taz'
assert xleb.pathutils.posixpath_to_fspath('/../taz', rootpath=rootpath) == '/foo/bar/taz'


def test_is_safe_path():
"""Test if given path is safe relative to the given rootdir"""

rootpath = '/foo/bar'

assert xleb.pathutils.is_safe_fspath('/foo/bar', rootpath=rootpath) == True
assert xleb.pathutils.is_safe_fspath('/foo/bar/', rootpath=rootpath) == True

assert xleb.pathutils.is_safe_fspath('/foo', rootpath=rootpath) == False
assert xleb.pathutils.is_safe_fspath('/foo/', rootpath=rootpath) == False

assert xleb.pathutils.is_safe_fspath('./foo', rootpath=rootpath) == False
assert xleb.pathutils.is_safe_fspath('./foo/', rootpath=rootpath) == False

assert xleb.pathutils.is_safe_fspath('../foo', rootpath=rootpath) == False
assert xleb.pathutils.is_safe_fspath('../foo/', rootpath=rootpath) == False

assert xleb.pathutils.is_safe_fspath('~/foo', rootpath=rootpath) == False
assert xleb.pathutils.is_safe_fspath('~/foo/', rootpath=rootpath) == False
21 changes: 18 additions & 3 deletions xleb/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,24 @@ def main():

# Middlewares
import xleb.fmiddleware
state.app.middlewares.append(aiohttp_middlewares.cors_middleware(
allow_all=True
))

if config.origins:
import re
origins = [
origin if '*' not in origin else re.compile(origin.replace('.', '\\.').replace('*', '.*'))
for origin in config.origins
]
print(origins)
state.app.middlewares.append(aiohttp_middlewares.cors_middleware(
origins=origins,
allow_methods=[ 'GET', 'POST' ],
allow_headers=[ '*' ],
allow_credentials=True
))
else:
state.app.middlewares.append(aiohttp_middlewares.cors_middleware(
allow_all=True
))
state.app.middlewares.append(xleb.fmiddleware.log_request)
state.app.middlewares.append(xleb.fmiddleware.access_check)

Expand Down
16 changes: 14 additions & 2 deletions xleb/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import inspect
import os

from typing import List, Optional


def get_args() -> dict:
"""Get commandline arguments"""
Expand Down Expand Up @@ -66,6 +68,14 @@ def get_args() -> dict:
default=None,
)

parser.add_argument(
'--origins', '-r',
help='allowed origins for cors. by default allows all',
nargs='+',
type=str,
default=[],
)

return vars(parser.parse_args())


Expand All @@ -75,18 +85,20 @@ class XlebConfig:
def __init__(
self,
path: str='.',
port: int=8000,
port: int=9876,
host: str='0.0.0.0',
log_level: str='INFO',
log: bool=False,
password: str=None,
password: Optional[str]=None,
origins: List[str]=None,
):
self.path = os.path.abspath(path)
self.port = port
self.host = host
self.log_level = log_level.upper()
self.log = log
self.password = password
self.origins = origins

@staticmethod
def init():
Expand Down
Loading

0 comments on commit fdccf5f

Please sign in to comment.