#!/usr/bin/env python3
# Copyright (C) 2016-2017 Florian Festi
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
{_(box.__doc__) if box.__doc__ else ""}
{_("Create boxes and more with a laser cutter!")}
{_(''' Boxes.py is an Open Source box generator written in Python. It features both finished parametrized generators as well as a Python API for writing your own. It features finger and (flat) dovetail joints, flex cuts, holes and slots for screws, hinges, gears, pulleys and much more.''')}
%s
" % html.escape(s) for s in type(u"")(e).split(u"\n")) + """ """).encode("utf-8") ] def serveStatic(self, environ, start_response): filename = environ["PATH_INFO"][len("/static/"):] path = os.path.join(self.staticdir, filename) if (not re.match(r"[a-zA-Z0-9_/-]+\.[a-zA-Z0-9]+", filename) or not os.path.exists(path)): if re.match(r"samples/.*-thumb.jpg", filename): path = os.path.join(self.staticdir, "nothing.png") else: start_response("404 Not Found", [('Content-type', 'text/plain')]) return [b"Not found"] type_, encoding = mimetypes.guess_type(filename) if encoding is None: encoding = "utf-8" # Images do not have charset. Just bytes. Except text based svg. # Todo: fallback if type_ is None? if type_ is not None and "image" in type_ and type_ != "image/svg+xml": start_response("200 OK", [('Content-type', "%s" % type_)]) else: start_response("200 OK", [('Content-type', "%s; charset=%s" % (type_, encoding))]) f = open(path, 'rb') return environ['wsgi.file_wrapper'](f, 512*1024) def getURL(self, environ): url = environ['wsgi.url_scheme']+'://' if environ.get('HTTP_HOST'): url += environ['HTTP_HOST'] else: url += environ['SERVER_NAME'] if environ['wsgi.url_scheme'] == 'https': if environ['SERVER_PORT'] != '443': url += ':' + environ['SERVER_PORT'] else: if environ['SERVER_PORT'] != '80': url += ':' + environ['SERVER_PORT'] url += quote(environ.get('SCRIPT_NAME', '')) url += quote(environ.get('PATH_INFO', '')) if environ.get('QUERY_STRING'): url += '?' + environ['QUERY_STRING'] return url def serve(self, environ, start_response): if environ["PATH_INFO"].startswith("/static/"): return self.serveStatic(environ, start_response) status = '200 OK' headers = [('Content-type', 'text/html; charset=utf-8'), ('X-XSS-Protection', '1; mode=block'), ('X-Content-Type-Options', 'nosniff'), ('x-frame-options', 'SAMEORIGIN'), ('Referrer-Policy', 'no-referrer')] d = parse_qs(environ.get('QUERY_STRING', '')) name = environ["PATH_INFO"][1:] args = [unquote_plus(arg) for arg in environ.get('QUERY_STRING', '').split("&")] render = "0" for arg in args: if arg.startswith("render="): render = arg[len("render="):] lang = self.getLanguage(args, environ.get("HTTP_ACCEPT_LANGUAGE", "")) _ = lang.gettext box_cls = self.boxes.get(name, None) if not box_cls: start_response(status, headers) return self.menu(lang) if name == "TrayLayout2": box = box_cls(self, webargs=True) else: box = box_cls() if render == "0": defaults = { } for a in args: kv = a.split('=') if len(kv) == 2: k, v = kv defaults[k] = html.escape(v, True) start_response(status, headers) return self.args2html(name, box, lang, "./" + name, defaults=defaults) else: args = ["--"+ arg for arg in args if not arg.startswith("render=")] try: box.parseArgs(args) except (ArgumentParserError) as e: start_response(status, headers) return self.errorMessage(name, e, _) if name == "TrayLayout": start_response(status, headers) box.fillDefault(box.x, box.y) layout2 = boxes.generators.traylayout.TrayLayout2(self, webargs=True) layout2.argparser.set_defaults(layout=str(box)) return self.args2html( name, layout2, lang, action="TrayLayout2") if name == "TrayLayout2": try: box.parse(box.layout.split("\n")) except Exception as e: start_response(status, headers) return self.errorMessage(name, e, _) try: fd, box.output = tempfile.mkstemp() box.metadata["url"] = self.getURL(environ) box.open() box.render() box.close() except Exception as e: if not isinstance(e, ValueError): print("Exception during rendering:") traceback.print_exc() start_response("500 Internal Server Error", headers) return self.errorMessage(name, e, _) http_headers = box.formats.http_headers.get( box.format, [('Content-type', 'application/unknown; charset=utf-8')])[:] if box.format != "svg" or render == "2": extension = box.format if extension == "svg_Ponoko": extension = "svg" http_headers.append(('Content-Disposition', 'attachment; filename="%s.%s"' % (box.__class__.__name__, extension))) start_response(status, http_headers) result = open(box.output, 'rb').readlines() os.close(fd) os.remove(box.output) return (l for l in result) if __name__=="__main__": host = '' port = 8000 if len(sys.argv) > 1: tmp = sys.argv[1].split(':') if len(tmp) == 2: host = tmp[0] port = int(tmp[1]) else: port = int(tmp[0]) fc = FileChecker() fc.start() boxserver = BServer() httpd = make_server(host, port, boxserver.serve) print("BoxesServer serving on host:port %s:%s..." % (host, port) ) try: httpd.serve_forever() except KeyboardInterrupt: fc.stop() httpd.server_close() print("BoxesServer stops.") else: application = BServer().serve