Upload location is now platform dependent

win32 defaults to %APPDATA%/Cura/uploads
macos defaults to ~/Library/Application Support/Cura/uploads (I hope, can't test it...)
linux defaults to ~/.cura/uploads

Server now also checks if file to be uploaded or deleted ends on .gcode and makes filename secure before doing anything on the filesystem

Also added favicon ;) and some bla to the README.md
master
Gina Häußge 2012-12-27 00:04:12 +01:00
parent 909278897c
commit 375fffdd3f
5 changed files with 52 additions and 12 deletions

View File

@ -2,16 +2,36 @@
# coding=utf-8 # coding=utf-8
__author__ = 'Gina Häußge <osd@foosel.net>' __author__ = 'Gina Häußge <osd@foosel.net>'
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 from printer import Printer
import sys
import os import os
import fnmatch import fnmatch
BASEURL='/ajax/' APPNAME="Cura"
BASEURL="/ajax/"
SUCCESS={} 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") app = Flask("Cura.webui")
printer = Printer() printer = Printer()
@ -63,7 +83,7 @@ def printerMessages():
return jsonify(messages=printer.messages) return jsonify(messages=printer.messages)
@app.route(BASEURL + 'state/log', methods=['GET']) @app.route(BASEURL + 'state/log', methods=['GET'])
def printerMessages(): def printerLogs():
return jsonify(log=printer.log) return jsonify(log=printer.log)
@app.route(BASEURL + 'state/temperatures', methods=['GET']) @app.route(BASEURL + 'state/temperatures', methods=['GET'])
@ -164,8 +184,9 @@ def readGcodeFiles():
@app.route(BASEURL + 'gcodefiles/upload', methods=['POST']) @app.route(BASEURL + 'gcodefiles/upload', methods=['POST'])
def uploadGcodeFile(): def uploadGcodeFile():
file = request.files['gcode_file'] file = request.files['gcode_file']
if file != None: if file and allowed_file(file.filename):
filename = UPLOAD_FOLDER + os.sep + file.filename secure = secure_filename(file.filename)
filename = os.path.join(UPLOAD_FOLDER, secure)
file.save(filename) file.save(filename)
return readGcodeFiles() return readGcodeFiles()
@ -177,8 +198,12 @@ def loadGcodeFile():
@app.route(BASEURL + 'gcodefiles/delete', methods=['POST']) @app.route(BASEURL + 'gcodefiles/delete', methods=['POST'])
def deleteGcodeFile(): def deleteGcodeFile():
if request.values.has_key("filename"):
filename = request.values["filename"] filename = request.values["filename"]
os.remove(UPLOAD_FOLDER + os.sep + filename) if allowed_file(filename):
secure = UPLOAD_FOLDER + os.sep + secure_filename(filename)
if os.path.exists(secure):
os.remove(secure)
return readGcodeFiles() return readGcodeFiles()
def sizeof_fmt(num): def sizeof_fmt(num):
@ -191,6 +216,8 @@ def sizeof_fmt(num):
num /= 1024.0 num /= 1024.0
return "%3.1f%s" % (num, 'TB') return "%3.1f%s" % (num, 'TB')
def allowed_file(filename):
return "." in filename and filename.rsplit(".", 1)[1] in ALLOWED_EXTENSIONS
def run(): def run():
app.debug = True app.run(host="0.0.0.0", port=5000)
app.run(host="0.0.0.0")

View File

@ -38,7 +38,7 @@ class Printer():
def connect(self): def connect(self):
if self.comm != None: if self.comm != None:
self.comm.close() self.comm.close()
self.comm = machineCom.MachineCom(port="COM4", baudrate=115200, callbackObject=self) self.comm = machineCom.MachineCom(callbackObject=self)
def disconnect(self): def disconnect(self):
if self.comm != None: if self.comm != None:
@ -193,5 +193,5 @@ class Printer():
if self.comm == None: if self.comm == None:
return return
self.comm.cancelPrint() self.comm.cancelPrint()
self.comm.sendCommand("M84") self.comm.sendCommands(["M84", "M104 S0", "M140 S0"]) # disable motors, switch off heaters

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

View File

@ -3,6 +3,8 @@
<head> <head>
<title>Cura WebUI</title> <title>Cura WebUI</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}">
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet" media="screen"> <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet" media="screen">
<link href="{{ url_for('static', filename='css/jquery.fileupload-ui.css') }}" rel="stylesheet" media="screen"> <link href="{{ url_for('static', filename='css/jquery.fileupload-ui.css') }}" rel="stylesheet" media="screen">
<link href="{{ url_for('static', filename='css/ui.css') }}" rel="stylesheet" media="screen"> <link href="{{ url_for('static', filename='css/ui.css') }}" rel="stylesheet" media="screen">

View File

@ -83,3 +83,14 @@ At time of writing, pyobjc 2.5 is not available at pypi. You have to clone repo
###Packaging ###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. 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`.