machine-unlimited-mobile/server.py

105 lines
3.6 KiB
Python

#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import urllib.request
import os
import re
# Whitelist of allowed domains
ALLOWED_DOMAINS = [
'en.wikipedia.org',
'wikipedia.org',
'example.com',
'github.com',
'www.github.com',
]
class Handler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path.startswith('/proxy?'):
qs = urlparse(self.path).query
params = parse_qs(qs)
if 'url' not in params:
self.send_error(400)
return
url = params['url'][0]
# Security: Validate URL
try:
parsed = urlparse(url)
# Block dangerous schemes
if parsed.scheme not in ('http', 'https'):
self.send_error(403, 'Invalid URL scheme')
return
# Block localhost/private IPs
hostname = parsed.hostname or ''
if hostname in ('localhost', '127.0.0.1', '::1') or hostname.startswith('192.168.') or hostname.startswith('10.'):
self.send_error(403, 'Local network access blocked')
return
# Check whitelist (optional - comment out to allow all)
# if not any(hostname.endswith(domain) for domain in ALLOWED_DOMAINS):
# self.send_error(403, 'Domain not whitelisted')
# return
except Exception as e:
self.send_error(400, 'Invalid URL')
return
try:
req = urllib.request.Request(url, headers={
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5'
})
response = urllib.request.urlopen(req, timeout=30)
data = response.read(1000000).decode('utf-8', errors='ignore')
# Add base tag for relative URLs
base_tag = f'<base href="{url}">'
if '<head>' in data:
data = data.replace('<head>', f'<head>{base_tag}', 1)
else:
data = f'<head>{base_tag}</head>' + data
# Inject click handler
script = '''<script>
document.addEventListener('click', (e) => {
const link = e.target.closest('a[href]');
if (link) {
e.preventDefault();
window.parent.postMessage({
type: 'linkTapped',
href: link.href,
label: link.textContent.trim()
}, '*');
}
}, true);
</script>'''
if '</body>' in data:
data = data.replace('</body>', script + '</body>', 1)
else:
data += script
self.send_response(200)
self.send_header('Content-Type', 'text/html; charset=utf-8')
self.send_header('X-Frame-Options', 'ALLOWALL')
self.end_headers()
self.wfile.write(data.encode('utf-8'))
except Exception as e:
self.send_error(500)
return
super().do_GET()
def log_message(self, *args):
pass
if __name__ == '__main__':
os.chdir('/tmp/machine.unlimited.pizza')
HTTPServer(('127.0.0.1', 9001), Handler).serve_forever()