This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
barkshark-web/bsweb/handlers/protocol.py

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())