Initial commit
This commit is contained in:
commit
8c26558f2a
146
.gitignore
vendored
Normal file
146
.gitignore
vendored
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
### Python template
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
.venv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# ====================
|
||||||
|
|
||||||
|
files/*
|
||||||
|
subdomain_files/*
|
||||||
|
!.gitkeep
|
113
autoindex.py
Normal file
113
autoindex.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
from bottle import route, request, run, redirect, template, default_app, abort
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from mimetypes import guess_type
|
||||||
|
|
||||||
|
base_hosts = [
|
||||||
|
'127.0.0.1.xip.io:8080'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def format_size(size):
|
||||||
|
for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
|
||||||
|
if size < 2048:
|
||||||
|
return f'{size} {unit}'
|
||||||
|
else:
|
||||||
|
size //= 1024
|
||||||
|
return f'{size} PiB'
|
||||||
|
|
||||||
|
|
||||||
|
def format_date(ts):
|
||||||
|
return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
|
||||||
|
def get_sort_icon(test, sort):
|
||||||
|
if sort == test:
|
||||||
|
return '<i class="sort descending icon"></i>'
|
||||||
|
elif sort == f'-{test}':
|
||||||
|
return '<i class="sort ascending icon"></i>'
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def get_sort_link(current, sort, hidden):
|
||||||
|
return f'?sort={"-" if current == sort else ""}{sort}{"&hidden" if hidden else ""}'
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_icon(name):
|
||||||
|
t = guess_type(name)[0].split('/')[0]
|
||||||
|
if t in ['text', 'image', 'audio', 'video']:
|
||||||
|
return t
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
class ListEntry:
|
||||||
|
def __init__(self, dir, name):
|
||||||
|
path = os.path.join(dir, name)
|
||||||
|
self.name = name
|
||||||
|
self.isdir = os.path.isdir(path)
|
||||||
|
self.size = os.path.getsize(path)
|
||||||
|
self.created = os.path.getctime(path)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_path(domain, path):
|
||||||
|
if domain in base_hosts:
|
||||||
|
return os.path.join(os.path.dirname(__file__), 'files', *path.split('/'))
|
||||||
|
else:
|
||||||
|
for host in base_hosts:
|
||||||
|
if host in domain:
|
||||||
|
return os.path.join(os.path.dirname(__file__), 'subdomain_files',
|
||||||
|
domain[:domain.index(host)-1], *path.split('/'))
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
def list_dir(dir, sort=None, hidden=False):
|
||||||
|
lst = [ListEntry(dir, name) for name in os.listdir(dir) if hidden or not name.startswith('.')]
|
||||||
|
lst = sorted(lst, key={
|
||||||
|
'name': lambda item: (not item.isdir, item.name.lower()),
|
||||||
|
'-name': lambda item: (item.isdir, item.name.lower()),
|
||||||
|
'size': lambda item: (not item.isdir, item.size),
|
||||||
|
'-size': lambda item: (item.isdir, item.size),
|
||||||
|
'created': lambda item: (not item.isdir, item.created),
|
||||||
|
'-created': lambda item: (item.isdir, item.created)
|
||||||
|
}[sort], reverse=sort.startswith('-'))
|
||||||
|
return lst
|
||||||
|
|
||||||
|
|
||||||
|
@route('/')
|
||||||
|
@route('/<path:path>')
|
||||||
|
def index(path=''):
|
||||||
|
domain = request.urlparts.netloc
|
||||||
|
query = request.urlparts.query
|
||||||
|
try:
|
||||||
|
resolved_path = resolve_path(domain, path)
|
||||||
|
except ValueError:
|
||||||
|
return 'GTFO'
|
||||||
|
if os.path.isdir(resolved_path):
|
||||||
|
if path and path[-1] != '/':
|
||||||
|
return redirect(f'/{path}/')
|
||||||
|
|
||||||
|
hidden = 'hidden' in request.GET
|
||||||
|
sort = request.GET.get('sort', 'name')
|
||||||
|
if sort not in ['name', '-name', 'size', '-size', 'created', '-created']:
|
||||||
|
sort = 'name'
|
||||||
|
|
||||||
|
return template('filelist',
|
||||||
|
lst=list_dir(resolved_path, sort, hidden),
|
||||||
|
format_size=format_size,
|
||||||
|
format_date=format_date,
|
||||||
|
get_sort_icon=get_sort_icon,
|
||||||
|
get_sort_link=get_sort_link,
|
||||||
|
sort=sort,
|
||||||
|
hidden=hidden,
|
||||||
|
path=path,
|
||||||
|
query=query,
|
||||||
|
guess_type=guess_type,
|
||||||
|
get_file_icon=get_file_icon)
|
||||||
|
else:
|
||||||
|
return abort(404)
|
||||||
|
|
||||||
|
application = default_app()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run(host='localhost', port=8080, debug=True, reloader=True)
|
27
configs/nginx.conf
Normal file
27
configs/nginx.conf
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name drop.217.182.90.36.xip.io;
|
||||||
|
|
||||||
|
location /_ {
|
||||||
|
alias /srv/apps/drop/files;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
include uwsgi_params;
|
||||||
|
uwsgi_pass unix:///tmp/drop.sock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name ~^(?<dir>.*)\.drop\.217\.182\.90\.36\.xip\.io$;
|
||||||
|
|
||||||
|
location /_ {
|
||||||
|
alias /srv/apps/drop/subdomain_files/$dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
include uwsgi_params;
|
||||||
|
uwsgi_pass unix:///tmp/drop.sock;
|
||||||
|
}
|
||||||
|
}
|
9
configs/supervisor.conf
Normal file
9
configs/supervisor.conf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[program:drop]
|
||||||
|
user = www-data
|
||||||
|
directory = /srv/apps/drop
|
||||||
|
command = /srv/apps/drop/venv/bin/uwsgi --ini /srv/apps/drop/configs/uwsgi.ini
|
||||||
|
autostart = true
|
||||||
|
autorestart = true
|
||||||
|
stderr_logfile = /srv/apps/drop/logs/uwsgi_err.log
|
||||||
|
stdout_logfile = /srv/apps/drop/logs/uwsgi_out.log
|
||||||
|
stopsignal = INT
|
6
configs/uwsgi.ini
Normal file
6
configs/uwsgi.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[uwsgi]
|
||||||
|
socket = /tmp/drop.sock
|
||||||
|
module = autoindex:application
|
||||||
|
master = true
|
||||||
|
processes = 2
|
||||||
|
enable-threads = true
|
79
filelist.tpl
Normal file
79
filelist.tpl
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>File list</title>
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/reset.min.css" rel="stylesheet" />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/site.min.css" rel="stylesheet" />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/icon.min.css" rel="stylesheet" />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/table.min.css" rel="stylesheet" />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/components/container.min.css" rel="stylesheet" />
|
||||||
|
<style>
|
||||||
|
table tbody tr {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
table tbody tr a {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="ui main container" style="padding: 15px 0">
|
||||||
|
<h2>Directory Index - /{{ path }}</h2>
|
||||||
|
<table class="ui selectable unstackable table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><a href="{{ get_sort_link(sort, 'name', hidden) }}">
|
||||||
|
Name {{ !get_sort_icon('name', sort) }}
|
||||||
|
</a></th>
|
||||||
|
<th style="width: 100px;"><a href="{{ get_sort_link(sort, 'size', hidden) }}">
|
||||||
|
Size {{ !get_sort_icon('size', sort) }}
|
||||||
|
</a></th>
|
||||||
|
<th style="width: 170px;"><a href="{{ get_sort_link(sort, 'created', hidden) }}">
|
||||||
|
Created {{ !get_sort_icon('created', sort) }}
|
||||||
|
</a></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
% if path:
|
||||||
|
<tr style="cursor: pointer">
|
||||||
|
<td>
|
||||||
|
<a href="../{{ f'?{query}' if query else '' }}"></a>
|
||||||
|
<i class="level up icon"></i>
|
||||||
|
../
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
% end
|
||||||
|
% for item in lst:
|
||||||
|
<tr style="cursor: pointer">
|
||||||
|
% if item.isdir:
|
||||||
|
<td>
|
||||||
|
<a href="{{ item.name }}/{{ f'?{query}' if query else '' }}"></a>
|
||||||
|
<i class="folder outline icon"></i>
|
||||||
|
{{ item.name }}/
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
% else:
|
||||||
|
<td>
|
||||||
|
<a href="/_/{{ path }}{{ item.name }}" target="_blank"></a>
|
||||||
|
<i class="file {{ get_file_icon(item.name) }} outline icon"></i>
|
||||||
|
{{ item.name }} [{{ guess_type(item.name)[0] }}]
|
||||||
|
</td>
|
||||||
|
<td><span title="{{ item.size }} byte(s)">{{ format_size(item.size) }}</span></td>
|
||||||
|
<td>{{ format_date(item.created) }}</td>
|
||||||
|
% end
|
||||||
|
</tr>
|
||||||
|
% end
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
0
files/.gitkeep
Normal file
0
files/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
0
subdomain_files/.gitkeep
Normal file
0
subdomain_files/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user