280 lines
6.9 KiB
Python
280 lines
6.9 KiB
Python
import json, mimetypes, ftplib
|
|
|
|
from os.path import isfile, basename, splitext, join, dirname, abspath, expanduser
|
|
from urllib.parse import urlparse, unquote, parse_qs as qsparse
|
|
|
|
import tldextract, pysftp
|
|
|
|
from IzzyLib import logging
|
|
from IzzyLib.color import *
|
|
from IzzyLib.misc import Path
|
|
from jinja2.exceptions import TemplateNotFound
|
|
from gi.repository import GLib, Gio
|
|
|
|
from ..config import var, dirs
|
|
from ..database import db
|
|
from ..functions import Client, Error, Notif, ParseQuery, HumanBytes, FinishRequest
|
|
|
|
|
|
def Local(request):
|
|
url = request.get_uri()
|
|
mime = mimetypes.guess_type(url)[0] or 'text/html'
|
|
webview = request.get_web_view()
|
|
parsed = urlparse(url)
|
|
urlquery = ParseQuery(parsed.query)
|
|
path = parsed.path.replace('/', '', 1)
|
|
page = parsed.netloc
|
|
data = {}
|
|
|
|
if not page:
|
|
page = 'home'
|
|
|
|
if page == 'home':
|
|
data['links'] = []
|
|
|
|
for row in db.fetch('links', single=False):
|
|
bmark = db.fetch('bookmarks', id=row.bookmarkid)
|
|
|
|
if bmark:
|
|
data['links'].append(bmark)
|
|
|
|
elif page == 'preferences':
|
|
data['settings'] = {
|
|
'font': 'sans undertale',
|
|
'font-size': '14'
|
|
}
|
|
|
|
elif page == 'bookmarks':
|
|
with db.session() as s:
|
|
if path.startswith('update'):
|
|
s.put.bookmark(**urlquery)
|
|
page = 'bookmarks'
|
|
url = f'{var.local}bookmarks'
|
|
|
|
if path.startswith('delete'):
|
|
markid = path.split('/')[1]
|
|
s.delete.bookmark(markid)
|
|
page = 'bookmarks'
|
|
url = f'{var.local}bookmarks'
|
|
|
|
if path.startswith('new'):
|
|
s.put.bookmark(urlquery)
|
|
page = 'bookmarks'
|
|
url = f'{var.local}bookmarks'
|
|
|
|
if path.startswith('edit'):
|
|
markid = path.split('/')[1]
|
|
bookmark = s.fetch('bookmarks', id=markid)
|
|
link = s.fetch('links')
|
|
|
|
if not bookmark:
|
|
_error('Invalid bookmark ID', webview)
|
|
|
|
data = {'bookmark': bookmark}
|
|
page = 'bookmark-edit'
|
|
|
|
else:
|
|
bookmarks = {}
|
|
rows = s.fetch('bookmarks', single=False)
|
|
|
|
if rows:
|
|
for row in rows:
|
|
category = row.category
|
|
|
|
if category not in bookmarks.keys():
|
|
bookmarks[category] = []
|
|
|
|
bookmarks[category].append(row)
|
|
|
|
data = {'bookmarks': bookmarks}
|
|
|
|
elif page == 'resource':
|
|
if path.endswith('css'):
|
|
data = {
|
|
'primary': '#e7a',
|
|
'secondary': '#e7a',
|
|
'background': '#191919',
|
|
'positive': '#ada',
|
|
'negative': '#daa'
|
|
}
|
|
|
|
return FinishRequest(request, var.template.render('css/' + path, data).encode('UTF-8'), mime)
|
|
|
|
elif path.endswith('js'):
|
|
with dirs.localweb.join('js').join(path).open() as fd:
|
|
return FinishRequest(request, fd.read(), mime)
|
|
|
|
else:
|
|
with dirs.localweb.join(path).open('rb') as fd:
|
|
return FinishRequest(request, fd.read(), mime)
|
|
|
|
try:
|
|
return FinishRequest(request, var.template.render(f'page/{page}.haml', data), mime)
|
|
|
|
except TemplateNotFound as e:
|
|
_error(f'Missing template file: {e}', webview)
|
|
logging.debug(f'Missing template file: {e}')
|
|
|
|
|
|
def File(request):
|
|
url = request.get_uri()
|
|
path = Path(url.replace('local://', ''))
|
|
mime = mimetypes.guess_type(url)[0] or 'text/html'
|
|
|
|
if not path.isfile():
|
|
msg = f'The file ({path.str()}) does not exist'
|
|
return Error(request.get_web_view(), msg, title='File Not Found')
|
|
|
|
if any(map(url.endswith, ['html', 'xhtml'])):
|
|
with path.open() as fd:
|
|
return FinishRequest(request, fd.read(), mime)
|
|
|
|
elif mime.startswith('text') or any(map(url.endswith, ['js', 'css'])):
|
|
mime = 'text/html'
|
|
|
|
with path.open() as fd:
|
|
data = {
|
|
'lines': fd.readlines(),
|
|
'path': path.str(),
|
|
'filename': path.name
|
|
}
|
|
|
|
htmldata = var.template.render('page/text.haml', data)
|
|
return FinishRequest(request, htmldata, mime)
|
|
|
|
logging.error(f'handlers.proctocol.File: Unhandled file type ({mime}): {path}')
|
|
return True
|
|
|
|
|
|
def Sftp(request):
|
|
webview = request.get_web_view()
|
|
url = request.get_uri()
|
|
parsed = urlparse(url)
|
|
path = unquote(parsed.path)
|
|
hidden = False
|
|
username, domain = [parsed.username, parsed.hostname]
|
|
keypath = Path('~/.ssh/id_rsa')
|
|
key = keypath.str() if keypath.exists() else None
|
|
|
|
options = {
|
|
'username': username,
|
|
'port': parsed.port
|
|
}
|
|
|
|
with pysftp.Connection(domain, **{k:v for k,v in options.items() if v}, private_key=key) as sftp:
|
|
if sftp.isfile(path):
|
|
filename, ext = splitext(path)
|
|
|
|
if ext[1:] in ['xml', 'html']:
|
|
html = sftp.open(path).read().decode()
|
|
|
|
elif ext[1:] in ['py', 'ini', 'env', 'txt', 'json', 'sgrd', 'xspf', 'go', 'js', 'css', 'scss', 'log']:
|
|
output = sftp.open(path).read().decode().split('\n')
|
|
html = var.template.render('page/sftp.haml', {
|
|
'textlines': output,
|
|
'domain': domain,
|
|
'netloc': parsed.netloc,
|
|
'path': path if path != '/' else '',
|
|
'previous': dirname(abspath(path))
|
|
})
|
|
|
|
else:
|
|
return FinishRequest(request, sftp.open(path).read())
|
|
|
|
else:
|
|
data = sftp.listdir_attr(path)
|
|
dirs = []
|
|
files = []
|
|
|
|
for line in data:
|
|
if not hidden and line.filename.startswith('.'):
|
|
continue
|
|
|
|
filedata = {
|
|
'filename': line.filename,
|
|
'shortname': line.filename[:30] + '...' if len(line.filename) > 30 else line.filename,
|
|
'size': HumanBytes(line.st_size),
|
|
'user': line.st_uid,
|
|
'group': line.st_gid
|
|
}
|
|
|
|
if sftp.isfile(join(path, line.filename)):
|
|
files.append(filedata)
|
|
else:
|
|
dirs.append(filedata)
|
|
|
|
context = {
|
|
'directories': dirs,
|
|
'files': files,
|
|
'domain': domain,
|
|
'netloc': parsed.netloc,
|
|
'path': path if path != '/' else '',
|
|
'previous': dirname(abspath(path)),
|
|
'textlines': None
|
|
}
|
|
|
|
html = var.template.render('page/sftp.haml', context)
|
|
|
|
return FinishRequest(request, html)
|
|
|
|
|
|
## This is probably gonna get removed if I can't eventually get a protocol handler setup
|
|
def Ftp(request):
|
|
webview = request.get_web_view()
|
|
url = request.get_uri()
|
|
parsed = urlparse(url)
|
|
files = []
|
|
directories = []
|
|
|
|
with db.session(False) as s:
|
|
creds = s.fetch('ftpcreds', domain=parsed.netloc)
|
|
|
|
try:
|
|
with ftplib.FTP(parsed.netloc, user=username, passwd=password, timeout=10) as ftp:
|
|
ftp.set_debuglevel(2)
|
|
|
|
if creds:
|
|
ftp.login(creds.username, creds.password)
|
|
|
|
ftp.cwd(parsed.path)
|
|
|
|
for filename in ftp.nlst():
|
|
if filename.startswith('.'):
|
|
continue
|
|
|
|
try:
|
|
size = ftp.size(filename)
|
|
files.append((filename, size))
|
|
except Exception as e:
|
|
directories.append(filename)
|
|
|
|
files.sort()
|
|
directories.sort()
|
|
|
|
html = var.template.render(
|
|
'ftp.html',
|
|
{'directories': directories, 'files': files, 'domain': parsed, 'previous': dirname(abspath(parsed.path))}
|
|
)
|
|
FinishRequest(request, html)
|
|
|
|
except Exception as e:
|
|
logging.debug(e)
|
|
_error(e, webview)
|
|
|
|
|
|
def Source(self, request):
|
|
webview = request.get_web_view()
|
|
url = request.get_uri().replace('source://', 'https://')
|
|
src = Client.request(url)
|
|
|
|
if not src.data:
|
|
return
|
|
|
|
source = '\n' + BeautifulSoup(src.data.decode(), features='lxml').prettify()
|
|
html = var.template.render('source.html', {'data': source, 'filename': url})
|
|
FinishRequest(request, html)
|
|
|
|
|
|
def _error(msg, webview):
|
|
webview.load_html(var.template.render('error.haml', {'error': msg, 'actions': {}}), webview.get_uri())
|