174 lines
4.9 KiB
Python
174 lines
4.9 KiB
Python
import io
|
|
import os
|
|
import sys
|
|
import json
|
|
import hashlib
|
|
import tempfile
|
|
|
|
from flask import Flask, request, send_from_directory
|
|
|
|
|
|
def _fd(f):
|
|
return f.fileno() if hasattr(f, 'fileno') else f
|
|
|
|
|
|
if os.name == 'nt':
|
|
import msvcrt
|
|
from ctypes import (sizeof, c_ulong, c_void_p, c_int64, Structure, Union, POINTER, windll, byref)
|
|
from ctypes.wintypes import BOOL, DWORD, HANDLE
|
|
|
|
LOCK_SH = 0x0
|
|
LOCK_NB = 0x1
|
|
LOCK_EX = 0x2
|
|
LOCK_UN = 0x9
|
|
|
|
if sizeof(c_ulong) != sizeof(c_void_p):
|
|
ULONG_PTR = c_int64
|
|
else:
|
|
ULONG_PTR = c_ulong
|
|
|
|
PVOID = c_void_p
|
|
|
|
|
|
class _OFFSET(Structure):
|
|
_fields_ = [
|
|
('Offset', DWORD),
|
|
('OffsetHigh', DWORD)
|
|
]
|
|
|
|
|
|
class _OFFSET_UNION(Union):
|
|
_fields_ = [
|
|
('_offset', _OFFSET),
|
|
('Pointer', PVOID)
|
|
]
|
|
_anonymous_ = ['_offset']
|
|
|
|
|
|
class OVERLAPPED(Structure):
|
|
_fields_ = [
|
|
('Internal', ULONG_PTR),
|
|
('InternalHigh', ULONG_PTR),
|
|
('_offset_union', _OFFSET_UNION),
|
|
('hEvent', HANDLE)
|
|
]
|
|
_anonymous_ = ['_offset_union']
|
|
|
|
|
|
LPOVERLAPPED = POINTER(OVERLAPPED)
|
|
LockFileEx = windll.kernel32.LockFileEx
|
|
LockFileEx.restype = BOOL
|
|
LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED]
|
|
UnlockFileEx = windll.kernel32.UnlockFileEx
|
|
UnlockFileEx.restype = BOOL
|
|
UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED]
|
|
|
|
|
|
def flock(f, flags):
|
|
hfile = msvcrt.get_osfhandle(_fd(f))
|
|
overlapped = OVERLAPPED()
|
|
if flags == LOCK_UN:
|
|
ret = UnlockFileEx(
|
|
hfile,
|
|
0,
|
|
0,
|
|
0xFFFF0000,
|
|
byref(overlapped)
|
|
)
|
|
else:
|
|
ret = LockFileEx(
|
|
hfile,
|
|
flags,
|
|
0,
|
|
0,
|
|
0xFFFF0000,
|
|
byref(overlapped)
|
|
)
|
|
return bool(ret)
|
|
else:
|
|
try:
|
|
import fcntl
|
|
|
|
LOCK_SH = fcntl.LOCK_SH
|
|
LOCK_NB = fcntl.LOCK_NB
|
|
LOCK_EX = fcntl.LOCK_EX
|
|
LOCK_UN = fcntl.LOCK_UN
|
|
except (ImportError, AttributeError):
|
|
LOCK_EX = LOCK_SH = LOCK_NB = 0
|
|
|
|
|
|
def flock(f, flags):
|
|
return flags == LOCK_UN
|
|
else:
|
|
def flock(f, flags):
|
|
return fcntl.flock(_fd(f), flags) == 0
|
|
|
|
|
|
def getJson(file, data=None):
|
|
if os.path.exists(file):
|
|
try:
|
|
return json.loads(open(file=file, mode='r', encoding='utf-8').read())
|
|
except json.decoder.JSONDecodeError:
|
|
return data
|
|
return data
|
|
|
|
|
|
def md5(input_data):
|
|
if isinstance(input_data, bytes):
|
|
return hashlib.md5(input_data).hexdigest()
|
|
if isinstance(input_data, str):
|
|
return hashlib.md5(bytes(input_data, encoding='utf-8')).hexdigest()
|
|
md5_object = hashlib.md5()
|
|
while True:
|
|
data = input_data.read(io.DEFAULT_BUFFER_SIZE)
|
|
if data:
|
|
md5_object.update(data)
|
|
else:
|
|
return md5_object.hexdigest()
|
|
|
|
|
|
www_home = os.path.abspath(os.path.join(os.path.dirname(__file__), 'apps'))
|
|
app_data = []
|
|
app = Flask(__name__)
|
|
|
|
|
|
@app.route('/getApps', methods=['GET', 'POST'])
|
|
def get_apps():
|
|
data = []
|
|
for i in app_data:
|
|
data.append({'url': '%s://%s/%s' % (request.scheme, request.host, i['packages_path']), 'md5': i['md5'], 'manifest': i['manifest']})
|
|
return data
|
|
|
|
|
|
@app.route('/', methods=['GET', 'POST'])
|
|
def index():
|
|
return 'Hello world.'
|
|
|
|
|
|
@app.route('/<path:filename>')
|
|
def www(filename):
|
|
return send_from_directory(www_home, filename)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
f_lock = open(file=os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.lock' % hashlib.md5(bytes(__file__, encoding='utf-8')).hexdigest()[:16])), mode='w', encoding='utf-8')
|
|
if (not flock(f_lock, LOCK_EX | LOCK_NB)) == 1:
|
|
sys.exit(1)
|
|
else:
|
|
print('Scanning apps...')
|
|
if os.path.exists(www_home):
|
|
for item in os.listdir(www_home):
|
|
if (item.endswith('.zip')) is bool(1):
|
|
packages = os.path.join(www_home, item)
|
|
manifest = os.path.join(www_home, '%s.%s' % (os.path.splitext(os.path.basename(item))[0], 'MANIFEST'))
|
|
if (os.path.isfile(packages) and os.path.isfile(manifest)) is bool(1):
|
|
info = getJson(manifest, {})
|
|
try:
|
|
if (isinstance(info['appName'], str) and isinstance(info['HomeFolderName'], str) and isinstance(info['shortcutMapping'], list)) is bool(0):
|
|
continue
|
|
app_data.append({'packages_path': item, 'md5': md5(open(packages, 'rb')), 'manifest': info})
|
|
except KeyError:
|
|
pass
|
|
print('Starting web server...')
|
|
app.run(host='0.0.0.0', port=9988)
|