|
|
@@ -0,0 +1,183 @@ |
|
|
|
#!/usr/bin/python |
|
|
|
|
|
|
|
import sys |
|
|
|
# Python 3. |
|
|
|
try: |
|
|
|
from http.server import HTTPServer |
|
|
|
from http.server import SimpleHTTPRequestHandler |
|
|
|
# Python 2. |
|
|
|
except ImportError: |
|
|
|
from BaseHTTPServer import HTTPServer |
|
|
|
from SimpleHTTPServer import SimpleHTTPRequestHandler |
|
|
|
import glob |
|
|
|
import os |
|
|
|
import base64 |
|
|
|
|
|
|
|
class HTTPRequestHandler(SimpleHTTPRequestHandler): |
|
|
|
# Implementation. |
|
|
|
def do_GET(self): |
|
|
|
tool.process(self) |
|
|
|
def do_POST(self): |
|
|
|
tool.process(self) |
|
|
|
|
|
|
|
def listFiles(path): |
|
|
|
items = [] |
|
|
|
|
|
|
|
fileNames = glob.glob(path + "/*") |
|
|
|
fileNames.sort() |
|
|
|
for fileName in fileNames: |
|
|
|
file = { } |
|
|
|
# Path. |
|
|
|
file["path"] = os.path.basename(fileName) |
|
|
|
# Type. |
|
|
|
file["type"] = None |
|
|
|
if (os.path.isdir(fileName)): |
|
|
|
file["type"] = "dir" |
|
|
|
elif (os.path.isfile(fileName)): |
|
|
|
file["type"] = "file"; |
|
|
|
|
|
|
|
items.append(file) |
|
|
|
|
|
|
|
return items |
|
|
|
def fileListToJSON(fileList): |
|
|
|
out = "" |
|
|
|
for file in fileList: |
|
|
|
if (len(out)): |
|
|
|
out += "," |
|
|
|
out += "{\"path\":\"%s\",\"type\":\"%s\"}" % (file["path"], file["type"]) |
|
|
|
return "[" + out + "]" |
|
|
|
def jsonToPathContents(json): |
|
|
|
# This function takes `abc` and `def` from string of the following format: |
|
|
|
# `{"path": "abc", "contents": "def"}`. |
|
|
|
parts = json.split('"') |
|
|
|
if (len(parts) == 9): |
|
|
|
return (parts[3], parts[7]) |
|
|
|
return (None, None) |
|
|
|
|
|
|
|
class Tool(object): |
|
|
|
# Configuration. |
|
|
|
def __init__(self, arguments): |
|
|
|
self.arguments = arguments |
|
|
|
self.PORT = 8000 |
|
|
|
self.serverHost = "" |
|
|
|
# Main execution sequence. |
|
|
|
def run(self): |
|
|
|
self.validateArguments() |
|
|
|
self.parseArguments() |
|
|
|
self.printArguments() |
|
|
|
self.runServer() |
|
|
|
# Implementation. |
|
|
|
def validateArguments(self): |
|
|
|
if (len(self.arguments) < 2): |
|
|
|
print( |
|
|
|
( |
|
|
|
"Usage: %s DIR [PORT]" |
|
|
|
"\n\n" |
|
|
|
"\tPORT defaults to 8000" |
|
|
|
) % self.arguments[0] |
|
|
|
) |
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
def printArguments(self): |
|
|
|
print("DIR: '%s'" % self.DIR) |
|
|
|
print("PORT: '%s'" % self.PORT) |
|
|
|
def parseArguments(self): |
|
|
|
self.DIR = self.arguments[1] |
|
|
|
# Override default port if specified. |
|
|
|
if (len(self.arguments) >= 3): |
|
|
|
self.PORT = self.arguments[2] |
|
|
|
def runServer(self): |
|
|
|
addr = (self.serverHost, int(self.PORT)) |
|
|
|
self.httpd = HTTPServer(addr, HTTPRequestHandler) |
|
|
|
self.httpd.serve_forever() |
|
|
|
def process(self, requestHandler): |
|
|
|
if (requestHandler.path == "/path"): |
|
|
|
self.processPath(requestHandler) |
|
|
|
if (requestHandler.path == "/list"): |
|
|
|
self.processFileList(requestHandler) |
|
|
|
if (requestHandler.path == "/read"): |
|
|
|
self.processReadFile(requestHandler) |
|
|
|
if (requestHandler.path == "/write"): |
|
|
|
self.processWriteFile(requestHandler) |
|
|
|
def processPath(self, request): |
|
|
|
request.send_response(200) |
|
|
|
request.send_header("Access-Control-Allow-Origin", "*") |
|
|
|
request.end_headers() |
|
|
|
|
|
|
|
data = self.DIR.encode() |
|
|
|
request.wfile.write(data) |
|
|
|
def processFileList(self, request): |
|
|
|
request.send_response(200) |
|
|
|
request.send_header("Access-Control-Allow-Origin", "*") |
|
|
|
request.end_headers() |
|
|
|
|
|
|
|
size = int(request.headers["Content-Length"]) |
|
|
|
path = request.rfile.read(size) |
|
|
|
path = path.decode() |
|
|
|
absPath = "%s/%s" % (self.DIR, path) |
|
|
|
|
|
|
|
fileList = listFiles(absPath) |
|
|
|
fileListJSON = fileListToJSON(fileList) |
|
|
|
data = fileListJSON.encode() |
|
|
|
request.wfile.write(data) |
|
|
|
def processReadFile(self, request): |
|
|
|
request.send_response(200) |
|
|
|
request.send_header("Access-Control-Allow-Origin", "*") |
|
|
|
request.end_headers() |
|
|
|
|
|
|
|
size = int(request.headers["Content-Length"]) |
|
|
|
path = request.rfile.read(size) |
|
|
|
path = path.decode() |
|
|
|
absPath = "%s/%s" % (self.DIR, path) |
|
|
|
print("Reading '%s'" % absPath) |
|
|
|
|
|
|
|
f = open(absPath, "r") |
|
|
|
contents = f.read() |
|
|
|
f.close() |
|
|
|
|
|
|
|
# Perform Python3 compatible encoding. |
|
|
|
# If this crashes for Python2 (when there are non-ASCII symbols), |
|
|
|
# it's probably fine for `contents` to stay intact. |
|
|
|
try: |
|
|
|
contents = contents.encode() |
|
|
|
except: |
|
|
|
pass |
|
|
|
|
|
|
|
request.wfile.write(contents) |
|
|
|
def processWriteFile(self, request): |
|
|
|
request.send_response(200) |
|
|
|
request.send_header("Access-Control-Allow-Origin", "*") |
|
|
|
request.end_headers() |
|
|
|
|
|
|
|
size = int(request.headers["Content-Length"]) |
|
|
|
data = request.rfile.read(size) |
|
|
|
|
|
|
|
# Extract path and contents. |
|
|
|
(path, contents) = jsonToPathContents(data) |
|
|
|
if ((path is None) or (contents is None)): |
|
|
|
print("ERROR Writing failed due to corrupt incoming data") |
|
|
|
|
|
|
|
# Try to convert using pre-Python2.4 API. |
|
|
|
try: |
|
|
|
contents = base64.decodestring(contents) |
|
|
|
# Resort to Python2.4+ API. |
|
|
|
except: |
|
|
|
contents = base64.b64decode(contents) |
|
|
|
|
|
|
|
# Perform Python3 compatible DEcoding. |
|
|
|
# If this crashes for Python2 (when there are non-ASCII symbols), |
|
|
|
# it's probably fine for `contents` to stay intact. |
|
|
|
try: |
|
|
|
contents = contents.decode() |
|
|
|
except: |
|
|
|
pass |
|
|
|
|
|
|
|
# Write. |
|
|
|
absPath = "%s/%s" % (self.DIR, path) |
|
|
|
print("Writing '%s'" % absPath) |
|
|
|
f = open(absPath, "w") |
|
|
|
f.write(contents) |
|
|
|
f.close() |
|
|
|
|
|
|
|
tool = Tool(sys.argv) |
|
|
|
tool.run() |