diff --git a/Cura/webui/__init__.py b/Cura/webui/__init__.py index 2114d86..fa9bd9e 100644 --- a/Cura/webui/__init__.py +++ b/Cura/webui/__init__.py @@ -2,16 +2,36 @@ # coding=utf-8 __author__ = 'Gina Häußge ' -from flask import Flask, request, render_template, jsonify +from flask import Flask, request, render_template, jsonify, make_response +from werkzeug import secure_filename from printer import Printer +import sys import os import fnmatch -BASEURL='/ajax/' +APPNAME="Cura" +BASEURL="/ajax/" SUCCESS={} -UPLOAD_FOLDER="uploads" + +# taken from http://stackoverflow.com/questions/1084697/how-do-i-store-desktop-application-data-in-a-cross-platform-way-for-python +if sys.platform == 'darwin': + from AppKit import NSSearchPathForDirectoriesInDomains + # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains + # NSApplicationSupportDirectory = 14 + # NSUserDomainMask = 1 + # True for expanding the tilde into a fully qualified path + appdata = os.path.join(NSSearchPathForDirectoriesInDomains(14, 1, True)[0], APPNAME) +elif sys.platform == 'win32': + appdata = os.path.join(os.environ['APPDATA'], APPNAME) +else: + appdata = os.path.expanduser(os.path.join("~", "." + APPNAME.lower())) + +UPLOAD_FOLDER = appdata + os.sep + "uploads" +if not os.path.isdir(UPLOAD_FOLDER): + os.makedirs(UPLOAD_FOLDER) +ALLOWED_EXTENSIONS = set(["gcode"]) app = Flask("Cura.webui") printer = Printer() @@ -63,7 +83,7 @@ def printerMessages(): return jsonify(messages=printer.messages) @app.route(BASEURL + 'state/log', methods=['GET']) -def printerMessages(): +def printerLogs(): return jsonify(log=printer.log) @app.route(BASEURL + 'state/temperatures', methods=['GET']) @@ -164,8 +184,9 @@ def readGcodeFiles(): @app.route(BASEURL + 'gcodefiles/upload', methods=['POST']) def uploadGcodeFile(): file = request.files['gcode_file'] - if file != None: - filename = UPLOAD_FOLDER + os.sep + file.filename + if file and allowed_file(file.filename): + secure = secure_filename(file.filename) + filename = os.path.join(UPLOAD_FOLDER, secure) file.save(filename) return readGcodeFiles() @@ -177,8 +198,12 @@ def loadGcodeFile(): @app.route(BASEURL + 'gcodefiles/delete', methods=['POST']) def deleteGcodeFile(): - filename = request.values["filename"] - os.remove(UPLOAD_FOLDER + os.sep + filename) + if request.values.has_key("filename"): + filename = request.values["filename"] + if allowed_file(filename): + secure = UPLOAD_FOLDER + os.sep + secure_filename(filename) + if os.path.exists(secure): + os.remove(secure) return readGcodeFiles() def sizeof_fmt(num): @@ -191,6 +216,8 @@ def sizeof_fmt(num): num /= 1024.0 return "%3.1f%s" % (num, 'TB') +def allowed_file(filename): + return "." in filename and filename.rsplit(".", 1)[1] in ALLOWED_EXTENSIONS + def run(): - app.debug = True - app.run(host="0.0.0.0") + app.run(host="0.0.0.0", port=5000) diff --git a/Cura/webui/printer.py b/Cura/webui/printer.py index 2111107..808e1c4 100644 --- a/Cura/webui/printer.py +++ b/Cura/webui/printer.py @@ -38,7 +38,7 @@ class Printer(): def connect(self): if self.comm != None: self.comm.close() - self.comm = machineCom.MachineCom(port="COM4", baudrate=115200, callbackObject=self) + self.comm = machineCom.MachineCom(callbackObject=self) def disconnect(self): if self.comm != None: @@ -193,5 +193,5 @@ class Printer(): if self.comm == None: return self.comm.cancelPrint() - self.comm.sendCommand("M84") + self.comm.sendCommands(["M84", "M104 S0", "M140 S0"]) # disable motors, switch off heaters diff --git a/Cura/webui/static/img/favicon.ico b/Cura/webui/static/img/favicon.ico new file mode 100644 index 0000000..1340f5d Binary files /dev/null and b/Cura/webui/static/img/favicon.ico differ diff --git a/Cura/webui/templates/index.html b/Cura/webui/templates/index.html index c0501b4..c44a24b 100644 --- a/Cura/webui/templates/index.html +++ b/Cura/webui/templates/index.html @@ -3,6 +3,8 @@ Cura WebUI + + diff --git a/README.md b/README.md index 5ace7af..41ff889 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,14 @@ At time of writing, pyobjc 2.5 is not available at pypi. You have to clone repo ###Packaging To package Cura into application bundle simply do `python setup.py py2app`. Resulting bundle is self-contained -- it includes Python and all needed packages. + +WebUI +===== + +This fork of Cura includes a WebUI for remote printing via the browser. It depends on the Python module "flask" and +its dependencies "werkzeug", "jinja2" and "itsdangerous", so you'll need those in order to run the WebUI. A simple +`pip install -r requirements.txt` or `pip install flask` should take care of that. + +Once installed, you can startup the WebUI instead of the regular Cura UI via the command-line option `--web` or `-w`. The +web interface will then be available on port 5000. If you want to change that (or the IP address the server binds to, +which currently is `0.0.0.0`), please take a look at the source code of `Cura/webui/__init__.py`. \ No newline at end of file