Skip to content

Instantly share code, notes, and snippets.

@KainokiKaede
Forked from omz/FileTransfer.py
Last active March 25, 2019 12:29
Show Gist options
  • Save KainokiKaede/9244241 to your computer and use it in GitHub Desktop.
Save KainokiKaede/9244241 to your computer and use it in GitHub Desktop.
#! python2
# APN file local installer
# Creates local HTTP server to serve APN file.
# Place APN file in the same directory of this script.
# If "address already in use" shown, re-run the script.
#
# Based on: File Transfer for Pythonista
# File Transfer for Pythonista
# ============================
# This script allows you to transfer Python files from
# and to Pythonista via local Wifi.
# It starts a basic HTTP server that you can access
# as a web page from your browser.
# When you upload a file that already exists, it is
# renamed automatically.
# From Pythonista's settings, you can add this script
# to the actions menu of the editor for quick access.
#
# Get Pythonista for iOS here:
# http://omz-software.com/pythonista
from BaseHTTPServer import BaseHTTPRequestHandler
import urlparse
import urllib
import cgi
import editor
import console
from socket import gethostname
import os
from cStringIO import StringIO
import webbrowser
TEMPLATE = ('<!DOCTYPE html><html><head>' +
'<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/'+
'css/bootstrap-combined.min.css" rel="stylesheet"></head><body>' +
'<div class="navbar"><div class="navbar-inner">' +
'<a class="brand" href="#">Pythonista File Transfer</a>' +
'</div></div><div class="container">' +
'<h2>Upload File</h2>{{ALERT}}'
'<p><form action="/" method="POST" enctype="multipart/form-data">' +
'<div class="form-actions">' +
'<input type="file" name="file"></input><br/><br/>' +
'<button type="submit" class="btn btn-primary">Upload</button>' +
'</div></form></p><hr/><h2>Download Files</h2>' +
'{{FILES}}</div></body></html>')
class TransferRequestHandler(BaseHTTPRequestHandler):
def get_unused_filename(self, filename):
if not os.path.exists(filename):
return filename
basename, ext = os.path.splitext(filename)
suffix_n = 1
while True:
alt_name = basename + '-' + str(suffix_n) + ext
if not os.path.exists(alt_name):
return alt_name
suffix_n += 1
def get_html_file_list(self):
buffer = StringIO()
buffer.write('<ul>')
root_dir = os.path.expanduser('.') # Changed from original.
files = []
for dn, dc, filenames in os.walk(root_dir):
for fn in filenames:
rel_dir = os.path.relpath(dn, root_dir)
if rel_dir != '.':
rel_file = os.path.join(rel_dir, fn)
else:
rel_file = fn
files.append(rel_file)
for filename in files:
if os.path.splitext(filename)[1] in ['.py', '.mobileconfig']: # Changed from original.
buffer.write('<li><a href="%s">%s</a></li>' % (filename, filename))
buffer.write('</ul>')
return buffer.getvalue()
def do_GET(self):
parsed_path = urlparse.urlparse(self.path)
path = parsed_path.path
if path == '/':
html = TEMPLATE
html = html.replace('{{ALERT}}', '')
html = html.replace('{{FILES}}', self.get_html_file_list())
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
self.wfile.write(html)
return
file_path = urllib.unquote(path)[1:]
if os.path.isfile(file_path):
self.send_response(200)
self.send_header('Content-Type', 'application/x-python')
self.send_header('Content-Disposition',
'attachment; filename=%s' % file_path)
self.end_headers()
with open(file_path, 'r') as f:
data = f.read()
self.wfile.write(data)
else:
html = TEMPLATE
html = html.replace('{{ALERT}}',
'<div class="alert alert-error">File not found</div>')
html = html.replace('{{FILES}}', self.get_html_file_list())
self.send_response(404)
self.send_header('Content-Type', 'text/html')
self.end_headers()
self.wfile.write(html)
def do_POST(self):
form = cgi.FieldStorage(fp=self.rfile, headers=self.headers,
environ={'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type']})
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
field_item = form['file']
uploaded_filename = None
dest_filename = None
file_data = field_item.file.read()
file_len = len(file_data)
uploaded_filename = field_item.filename
dest_filename = self.get_unused_filename(uploaded_filename)
with open(dest_filename, 'w') as f:
f.write(file_data)
editor.reload_files()
del file_data
html = TEMPLATE
if uploaded_filename != dest_filename:
message = '%s uploaded (renamed to %s).' % (uploaded_filename,
dest_filename)
else:
message = '%s uploaded.' % (uploaded_filename)
html = html.replace('{{ALERT}}',
'<div class="alert alert-success">%s</div>' % (message))
html = html.replace('{{FILES}}', self.get_html_file_list())
self.wfile.write(html)
if __name__ == '__main__':
console.clear()
from BaseHTTPServer import HTTPServer
server = HTTPServer(('', 8080), TransferRequestHandler)
URL = 'http://localhost:8080' # Changed from original.
print 'Open this page in your browser:'
console.set_font('Helvetica-Bold', 30)
print URL
console.set_font()
print 'Tap the stop button when you\'re done.'
webbrowser.get('safari').open(URL) # Changed from original.
server.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment