diff --git a/.gitignore b/.gitignore index 1c96ad61..472e3810 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +src/octoprint/templates/_data/AUTHORS.md +src/octoprint/templates/_data/CHANGELOG.md +src/octoprint/templates/_data/THIRDPARTYLICENSES.md + *.tar.bz2 *.tar.gz *.7z diff --git a/MANIFEST.in b/MANIFEST.in index 82ddf50b..abffeac2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,5 +4,8 @@ recursive-include src/octoprint/plugins * recursive-include src/octoprint/translations * include versioneer.py include src/octoprint/_version.py +include AUTHORS.md +include CHANGELOG.md +include LICENSE include README.md include requirements.txt diff --git a/THIRDPARTYLICENSES.md b/THIRDPARTYLICENSES.md new file mode 100644 index 00000000..2ac46c7d --- /dev/null +++ b/THIRDPARTYLICENSES.md @@ -0,0 +1,54 @@ +# Third Party Licenses + +## Web Interface + + * [AVLTree](https://gist.github.com/viking/2424106) (modified): GPL, LGPL (dual licensed) + * [Babel JavaScript Support](https://github.com/mitsuhiko/babel/blob/master/contrib/babel.js): BSD + * [Bootstrap](http://getbootstrap.com/): Apache License 2.0 + * [Bootstrap Modal](http://jschr.github.io/bootstrap-modal/): Apache License 2.0 + * [Bootstrap Slider Knockout Bindings](https://github.com/cosminstefanxp/bootstrap-slider-knockout-binding): MIT + * [Bootstrap Slider](http://seiyria.com/bootstrap-slider/): Apache License 2.0 + * [Bootstrap Tabdrop](http://www.eyecon.ro/bootstrap-tabdrop): Apache License 2.0 + * [Detect Mobile Browser](http://detectmobilebrowsers.com/): Public Domain + * [Flot](http://www.flotcharts.org/): MIT + * [JavaScript MD5](https://github.com/blueimp/JavaScript-MD5): MIT + * [JQuery](http://jquery.com/): MIT + * [JQuery Bootstrap Wizard](http://github.com/VinceG/twitter-bootstrap-wizard): MIT, GPL (dual licensed) + * [JQuery File Upload](https://github.com/blueimp/jQuery-File-Upload): MIT + * [JQuery iframe transport](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js): MIT + * [JQuery QRCode](http://larsjung.de/jquery-qrcode/): MIT + * [JQuery Slimscroll](http://rocha.la/jQuery-slimScroll): MIT, GPL (dual licensed) + * [JQuery UI Core, Mouse, Slider and Widget](http://jqueryui.com): MIT + * [Knockout](http://knockoutjs.com/): MIT + * [LESS](http://lesscss.org): Apache License 2.0 + * [lodash](https://lodash.com): MIT + * [Loglevel](https://github.com/pimterry/loglevel): MIT + * [Modernizr](http://modernizr.com): MIT + * [Moment.js](http://momentjs.com/): MIT + * [PNotify](http://sciactive.com/pnotify/): GPL, LGPL, MPL (triple licensed) + * [pusher.color.js](http://cache.preserve.io/5g18q0pw/index.html) (original link dead): MIT + * [SockJS](https://github.com/sockjs/sockjs-client): MIT + * [sprintf-js](http://alexei.ro/): BSD + +## Server + + * [Flask](http://flask.pocoo.org/): BSD + * [Flask-Assets](http://github.com/miracle2k/flask-assets): BSD + * [Flask-Babel](http://github.com/mitsuhiko/flask-babel): BSD + * [Flask-Login](https://flask-login.readthedocs.org/en/latest/https://github.com/maxcountryman/flask-login): MIT + * [Flask-Markdown](http://github.com/dcolish/flask-markdown): BSD + * [Flask-Principal](http://packages.python.org/Flask-Principal/): MIT + * [netaddr](https://github.com/drkjam/netaddr/): BSD + * [netifaces](https://bitbucket.org/al45tair/netifaces): MIT + * [pkginfo](http://pypi.python.org/pypi/pkginfo/): Python + * [psutil](https://github.com/giampaolo/psutil): BSD + * [pylru](https://github.com/jlhutch/pylru): GPLv2 + * [pyserial](http://pyserial.sourceforge.net/): Python + * [PyYAML](http://pyyaml.org/wiki/PyYAML): MIT + * [requests](http://python-requests.org/): Apache License 2.0 + * [rsa](http://stuvel.eu/rsa): Apache License 2.0 + * [sarge](http://sarge.readthedocs.org/): BSD + * [semantic_version](https://github.com/rbarrois/python-semanticversion): BSD + * [SockJS-Tornado](http://github.com/mrjoes/sockjs-tornado/): MIT + * [Tornado](http://www.tornadoweb.org/): Apache License 2.0 + * [watchdog](http://github.com/gorakhargosh/watchdog): Apache License 2.0 diff --git a/setup.py b/setup.py index 899135f2..fc2a74d6 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ # coding=utf-8 from setuptools import setup, find_packages +from distutils.command.build_py import build_py as _build_py import os import versioneer @@ -22,11 +23,12 @@ INSTALL_REQUIRES = [ "Flask-Principal==0.3.5", "Flask-Babel==0.9", "Flask-Assets==0.10", + "Flask-Markdown==0.3", "pyserial==2.7", "netaddr==0.7.17", "watchdog==0.8.3", "sarge==0.1.4", - "netifaces==0.8", + "netifaces==0.10", "pylru==1.0.9", "rsa==3.2", "pkginfo==1.2.1", @@ -62,6 +64,32 @@ DEPENDENCY_LINKS = [] #----------------------------------------------------------------------------------------------------------------------- # Anything below here is just command setup and general setup configuration +def data_copy_build_py_factory(files, baseclass): + class data_copy_build_py(baseclass): + files = dict() + + def run(self): + import shutil + if not self.dry_run: + for directory, files in self.__class__.files.items(): + target_dir = os.path.join(self.build_lib, directory) + self.mkpath(target_dir) + + for entry in files: + if isinstance(entry, tuple): + if len(entry) != 2: + continue + source, dest = entry + else: + source = dest = entry + shutil.copy(source, os.path.join(target_dir, dest)) + + baseclass.run(self) + + return type(data_copy_build_py)(data_copy_build_py.__name__, + (data_copy_build_py,), + dict(files=files)) + def get_cmdclass(): cmdclass = versioneer.get_cmdclass() @@ -74,6 +102,14 @@ def get_cmdclass(): bundled_dir = os.path.join("src", "octoprint", "translations") cmdclass.update(octoprint_setuptools.get_babel_commandclasses(pot_file=pot_file, output_dir=translation_dir, pack_name_prefix="OctoPrint-i18n-", pack_path_prefix="", bundled_dir=bundled_dir)) + cmdclass["build_py"] = data_copy_build_py_factory({ + "octoprint/templates/_data": [ + "AUTHORS.md", + "CHANGELOG.md", + "THIRDPARTYLICENSES.md", + ] + }, cmdclass["build_py"] if "build_py" in cmdclass else _build_py) + return cmdclass @@ -110,7 +146,7 @@ def params(): packages = find_packages(where="src") package_dir = { - "": "src" + "": "src", } package_data = { "octoprint": octoprint_setuptools.package_data_dirs('src/octoprint', ['static', 'templates', 'plugins', 'translations']) diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index 4e086a70..0f07577e 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -105,7 +105,20 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, def get_template_configs(self): return [ - dict(type="settings", name=gettext("Plugin Manager"), template="pluginmanager_settings.jinja2", custom_bindings=True) + dict(type="settings", name=gettext("Plugin Manager"), template="pluginmanager_settings.jinja2", custom_bindings=True), + dict(type="about", name=gettext("Plugin Licenses"), template="pluginmanager_about.jinja2") + ] + + def get_template_vars(self): + plugins = sorted(self._get_plugins(), key=lambda x: x["name"].lower()) + return dict( + all=plugins, + thirdparty=filter(lambda p: not p["bundled"], plugins) + ) + + def get_template_types(self, template_sorting, template_rules, *args, **kwargs): + return [ + ("about_thirdparty", dict(), dict(template=lambda x: x + "_about_thirdparty.jinja2")) ] ##~~ BlueprintPlugin @@ -161,19 +174,13 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, if not admin_permission.can(): return make_response("Insufficient rights", 403) - plugins = self._plugin_manager.plugins - - hidden = self._settings.get(["hidden"]) - result = [] - for name, plugin in plugins.items(): - if name in hidden: - continue - result.append(self._to_external_representation(plugin)) - if "refresh_repository" in request.values and request.values["refresh_repository"] in valid_boolean_trues: self._repository_available = self._refresh_repository() - return jsonify(plugins=result, repository=dict(available=self._repository_available, plugins=self._repository_plugins), os=self._get_os(), octoprint=self._get_octoprint_version_string()) + return jsonify(plugins=self._get_plugins(), + repository=dict(available=self._repository_available, plugins=self._repository_plugins), + os=self._get_os(), + octoprint=self._get_octoprint_version_string()) def on_api_command(self, command, data): if not admin_permission.can(): @@ -612,6 +619,18 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, octoprint_version = pkg_resources.parse_version(octoprint_version.base_version) return octoprint_version + def _get_plugins(self): + plugins = self._plugin_manager.plugins + + hidden = self._settings.get(["hidden"]) + result = [] + for name, plugin in plugins.items(): + if name in hidden: + continue + result.append(self._to_external_representation(plugin)) + + return result + def _to_external_representation(self, plugin): return dict( key=plugin.key, @@ -641,5 +660,6 @@ def __plugin_load__(): global __plugin_hooks__ __plugin_hooks__ = { - "octoprint.server.http.bodysize": __plugin_implementation__.increase_upload_bodysize + "octoprint.server.http.bodysize": __plugin_implementation__.increase_upload_bodysize, + "octoprint.ui.web.templatetypes": __plugin_implementation__.get_template_types } diff --git a/src/octoprint/plugins/pluginmanager/templates/pluginmanager_about.jinja2 b/src/octoprint/plugins/pluginmanager/templates/pluginmanager_about.jinja2 new file mode 100644 index 00000000..6c3cd1d9 --- /dev/null +++ b/src/octoprint/plugins/pluginmanager/templates/pluginmanager_about.jinja2 @@ -0,0 +1,18 @@ +

Plugin Licenses

+ + + +{% if templates.plugin_pluginmanager_about_thirdparty.order %} +

Licenses of Plugin Dependencies

+ + {% for key in templates.plugin_pluginmanager_about_thirdparty.order %} + {% set heading, config = templates.plugin_pluginmanager_about_thirdparty.entries[key] %} +

{{ heading }}

+ + {% include config.template ignore missing %} + {% endfor %} +{% endif %} diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index d5827f10..5dd13f00 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -12,6 +12,7 @@ from flask.ext.login import LoginManager, current_user from flask.ext.principal import Principal, Permission, RoleNeed, identity_loaded, UserNeed from flask.ext.babel import Babel, gettext, ngettext from flask.ext.assets import Environment, Bundle +from flaskext.markdown import Markdown from babel import Locale from watchdog.observers import Observer from watchdog.observers.polling import PollingObserver @@ -107,7 +108,7 @@ def load_user(id): #~~ startup code -class Server(): +class Server(object): def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False, logConf=None): self._configfile = configfile self._basedir = basedir @@ -596,6 +597,8 @@ class Server(): response.headers.add("X-Clacks-Overhead", "GNU Terry Pratchett") return response + Markdown(app) + def _setup_i18n(self, app): global babel global LOCALES @@ -623,20 +626,78 @@ class Server(): return self._get_locale() def _setup_jinja2(self): + import re + app.jinja_env.add_extension("jinja2.ext.do") app.jinja_env.add_extension("octoprint.server.util.jinja.trycatch") + def regex_replace(s, find, replace): + return re.sub(find, replace, s) + + html_header_regex = re.compile("[1-6])>(?P.*?)") + def offset_html_headers(s, offset): + def repl(match): + number = int(match.group("number")) + number += offset + if number > 6: + number = 6 + elif number < 1: + number = 1 + return "{content}".format(number=number, content=match.group("content")) + return html_header_regex.sub(repl, s) + + markdown_header_regex = re.compile("^(?P#+)\s+(?P.*)$", flags=re.MULTILINE) + def offset_markdown_headers(s, offset): + def repl(match): + number = len(match.group("hashs")) + number += offset + if number > 6: + number = 6 + elif number < 1: + number = 1 + return "{hashs} {content}".format(hashs="#" * number, content=match.group("content")) + return markdown_header_regex.sub(repl, s) + + app.jinja_env.filters["regex_replace"] = regex_replace + app.jinja_env.filters["offset_html_headers"] = offset_html_headers + app.jinja_env.filters["offset_markdown_headers"] = offset_markdown_headers + # configure additional template folders for jinja2 import jinja2 filesystem_loader = jinja2.FileSystemLoader([]) filesystem_loader.searchpath = self._template_searchpaths - jinja_loader = jinja2.ChoiceLoader([ - app.jinja_loader, - filesystem_loader - ]) + loaders = [app.jinja_loader, filesystem_loader] + if octoprint.util.is_running_from_source(): + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) + allowed = ["AUTHORS.md", "CHANGELOG.md", "THIRDPARTYLICENSES.md"] + + class SourceRootFilesystemLoader(jinja2.FileSystemLoader): + def __init__(self, template_filter, prefix, *args, **kwargs): + jinja2.FileSystemLoader.__init__(self, *args, **kwargs) + self._filter = template_filter + if not prefix.endswith("/"): + prefix += "/" + self._prefix = prefix + + def get_source(self, environment, template): + if not template.startswith(self._prefix): + raise jinja2.TemplateNotFound(template) + + template = template[len(self._prefix):] + if not self._filter(template): + raise jinja2.TemplateNotFound(template) + + return jinja2.FileSystemLoader.get_source(self, environment, template) + + def list_templates(self): + templates = jinja2.FileSystemLoader.list_templates(self) + return map(lambda t: self._prefix + t, filter(self._filter, templates)) + + loaders.append(SourceRootFilesystemLoader(lambda t: t in allowed, "_data/", root)) + + jinja_loader = jinja2.ChoiceLoader(loaders) app.jinja_loader = jinja_loader - del jinja2 self._register_template_plugins() diff --git a/src/octoprint/server/util/flask.py b/src/octoprint/server/util/flask.py index 93b53736..e14ab1ba 100644 --- a/src/octoprint/server/util/flask.py +++ b/src/octoprint/server/util/flask.py @@ -634,7 +634,8 @@ def collect_plugin_assets(enable_gcodeviewer=True, preferred_stylesheet="css"): 'js/app/viewmodels/users.js', 'js/app/viewmodels/log.js', 'js/app/viewmodels/usersettings.js', - 'js/app/viewmodels/wizard.js' + 'js/app/viewmodels/wizard.js', + 'js/app/viewmodels/about.js' ] if enable_gcodeviewer: assets["js"] += [ diff --git a/src/octoprint/server/views.py b/src/octoprint/server/views.py index 0a895d73..aca5e1a6 100644 --- a/src/octoprint/server/views.py +++ b/src/octoprint/server/views.py @@ -6,6 +6,7 @@ __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agp __copyright__ = "Copyright (C) 2015 The OctoPrint Project - Released under terms of the AGPLv3 License" import os +import datetime from collections import defaultdict from flask import request, g, url_for, make_response, render_template, send_from_directory, redirect @@ -49,6 +50,7 @@ def index(): settings=dict(div=lambda x: "settings_plugin_" + x, template=lambda x: x + "_settings.jinja2", to_entry=lambda data: (data["name"], data)), usersettings=dict(div=lambda x: "usersettings_plugin_" + x, template=lambda x: x + "_usersettings.jinja2", to_entry=lambda data: (data["name"], data)), wizard=dict(div=lambda x: "wizard_plugin_" + x, template=lambda x: x + "_wizard.jinja2", to_entry=lambda data: (data["name"], data)), + about=dict(div=lambda x: "about_plugin_" + x, template=lambda x: x + "_about.jinja2", to_entry=lambda data: (data["name"], data)), generic=dict(template=lambda x: x + ".jinja2", to_entry=lambda data: data) ) @@ -60,6 +62,7 @@ def index(): settings=dict(add="custom_append", key="name", custom_add_entries=lambda missing: dict(section_plugins=(gettext("Plugins"), None)), custom_add_order=lambda missing: ["section_plugins"] + missing), usersettings=dict(add="append", key="name"), wizard=dict(add="append", key="name", key_extractor=lambda d, k: "0:{}".format(d[0]) if "mandatory" in d[1] and d[1]["mandatory"] else "1:{}".format(d[0])), + about=dict(add="append", key="name"), generic=dict(add="append", key=None) ) @@ -184,6 +187,16 @@ def index(): firstrunend=(gettext("Finish"), dict(template="dialogs/wizard/firstrun_end.jinja2", _div="wizard_firstrun_end")), ) + # about dialog + + templates["about"]["entries"] = dict( + about=(gettext("About OctoPrint"), dict(template="dialogs/about/about.jinja2", _div="about_about", custom_bindings=False)), + license=(gettext("OctoPrint License"), dict(template="dialogs/about/license.jinja2", _div="about_license", custom_bindings=False)), + thirdparty=(gettext("Third Party Licenses"), dict(template="dialogs/about/thirdparty.jinja2", _div="about_thirdparty", custom_bindings=False)), + authors=(gettext("Authors"), dict(template="dialogs/about/authors.jinja2", _div="about_authors", custom_bindings=False)), + changelog=(gettext("Changelog"), dict(template="dialogs/about/changelog.jinja2", _div="about_changelog", custom_bindings=False)) + ) + # extract data from template plugins template_plugins = pluginManager.get_implementations(octoprint.plugin.TemplatePlugin) @@ -302,6 +315,7 @@ def index(): #~~ prepare full set of template vars for rendering wizard = bool(templates["wizard"]["order"]) + now = datetime.datetime.utcnow() render_kwargs = dict( webcamStream=settings().get(["webcam", "stream"]), enableTemperatureGraph=settings().get(["feature", "temperatureGraph"]), @@ -318,19 +332,18 @@ def index(): templates=templates, pluginNames=plugin_names, locales=locales, - wizard=wizard + wizard=wizard, + now=now ) render_kwargs.update(plugin_vars) #~~ render! - import datetime - response = make_response(render_template( "index.jinja2", **render_kwargs )) - response.headers["Last-Modified"] = datetime.datetime.now() + response.headers["Last-Modified"] = now if wizard: response = util.flask.add_non_caching_response_headers(response) @@ -419,6 +432,7 @@ def _process_template_config(name, implementation, rule, config=None, counter=1) return data + @app.route("/robots.txt") def robotsTxt(): return send_from_directory(app.static_folder, "robots.txt") diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index 502b1056..6fb9d95b 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -208,6 +208,7 @@ default_settings = { ], "usersettings": ["access", "interface"], "wizard": ["access"], + "about": ["about", "license", "thirdparty", "plugin_pluginmanager", "authors", "changelog"], "generic": [] }, "disabled": { diff --git a/src/octoprint/static/js/app/viewmodels/about.js b/src/octoprint/static/js/app/viewmodels/about.js new file mode 100644 index 00000000..2d251b9c --- /dev/null +++ b/src/octoprint/static/js/app/viewmodels/about.js @@ -0,0 +1,31 @@ +$(function() { + function AboutViewModel(parameters) { + var self = this; + + self.aboutDialog = undefined; + + self.show = function() { + self.aboutDialog.modal({ + minHeight: function() { return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); } + }).css({ + width: 'auto', + 'margin-left': function() { return -($(this).width() /2); } + }); + return false; + }; + + self.hide = function() { + self.aboutDialog.modal("hide"); + }; + + self.onStartup = function() { + self.aboutDialog = $('#about_dialog'); + }; + } + + OCTOPRINT_VIEWMODELS.push([ + AboutViewModel, + [], + ["#about_dialog", "#footer_about"] + ]); +}); diff --git a/src/octoprint/templates/_data/agpl.html b/src/octoprint/templates/_data/agpl.html new file mode 100644 index 00000000..6a274205 --- /dev/null +++ b/src/octoprint/templates/_data/agpl.html @@ -0,0 +1,677 @@ +

GNU AFFERO GENERAL PUBLIC LICENSE

+

Version 3, 19 November 2007

+ +

Copyright © 2007 Free Software Foundation, + Inc. <http://fsf.org/> +
+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU Affero General Public License is a free, copyleft license + for software and other kinds of works, specifically designed to ensure + cooperation with the community in the case of network server software.

+ +

The licenses for most software and other practical works are + designed to take away your freedom to share and change the works. By + contrast, our General Public Licenses are intended to guarantee your + freedom to share and change all versions of a program--to make sure it + remains free software for all its users.

+ +

When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + them if you wish), that you receive source code or can get it if you + want it, that you can change the software or use pieces of it in new + free programs, and that you know you can do these things.

+ +

Developers that use our General Public Licenses protect your rights + with two steps: (1) assert copyright on the software, and (2) offer + you this License which gives you legal permission to copy, distribute + and/or modify the software.

+ +

A secondary benefit of defending all users' freedom is that + improvements made in alternate versions of the program, if they + receive widespread use, become available for other developers to + incorporate. Many developers of free software are heartened and + encouraged by the resulting cooperation. However, in the case of + software used on network servers, this result may fail to come about. + The GNU General Public License permits making a modified version and + letting the public access it on a server without ever releasing its + source code to the public.

+ +

The GNU Affero General Public License is designed specifically to + ensure that, in such cases, the modified source code becomes available + to the community. It requires the operator of a network server to + provide the source code of the modified version running there to the + users of that server. Therefore, public use of a modified version, on + a publicly accessible server, gives the public access to the source + code of the modified version.

+ +

An older license, called the Affero General Public License and + published by Affero, was designed to accomplish similar goals. This is + a different license, not a version of the Affero GPL, but Affero has + released a new version of the Affero GPL which permits relicensing under + this license.

+ +

The precise terms and conditions for copying, distribution and + modification follow.

+ +

TERMS AND CONDITIONS

+ +

0. Definitions.

+ +

"This License" refers to version 3 of the GNU Affero General Public + License.

+ +

"Copyright" also means copyright-like laws that apply to other kinds + of works, such as semiconductor masks.

+ +

"The Program" refers to any copyrightable work licensed under this + License. Each licensee is addressed as "you". "Licensees" and + "recipients" may be individuals or organizations.

+ +

To "modify" a work means to copy from or adapt all or part of the work + in a fashion requiring copyright permission, other than the making of an + exact copy. The resulting work is called a "modified version" of the + earlier work or a work "based on" the earlier work.

+ +

A "covered work" means either the unmodified Program or a work based + on the Program.

+ +

To "propagate" a work means to do anything with it that, without + permission, would make you directly or secondarily liable for + infringement under applicable copyright law, except executing it on a + computer or modifying a private copy. Propagation includes copying, + distribution (with or without modification), making available to the + public, and in some countries other activities as well.

+ +

To "convey" a work means any kind of propagation that enables other + parties to make or receive copies. Mere interaction with a user through + a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays "Appropriate Legal Notices" + to the extent that it includes a convenient and prominently visible + feature that (1) displays an appropriate copyright notice, and (2) + tells the user that there is no warranty for the work (except to the + extent that warranties are provided), that licensees may convey the + work under this License, and how to view a copy of this License. If + the interface presents a list of user commands or options, such as a + menu, a prominent item in the list meets this criterion.

+ +

1. Source Code.

+ +

The "source code" for a work means the preferred form of the work + for making modifications to it. "Object code" means any non-source + form of a work.

+ +

A "Standard Interface" means an interface that either is an official + standard defined by a recognized standards body, or, in the case of + interfaces specified for a particular programming language, one that + is widely used among developers working in that language.

+ +

The "System Libraries" of an executable work include anything, other + than the work as a whole, that (a) is included in the normal form of + packaging a Major Component, but which is not part of that Major + Component, and (b) serves only to enable use of the work with that + Major Component, or to implement a Standard Interface for which an + implementation is available to the public in source code form. A + "Major Component", in this context, means a major essential component + (kernel, window system, and so on) of the specific operating system + (if any) on which the executable work runs, or a compiler used to + produce the work, or an object code interpreter used to run it.

+ +

The "Corresponding Source" for a work in object code form means all + the source code needed to generate, install, and (for an executable + work) run the object code and to modify the work, including scripts to + control those activities. However, it does not include the work's + System Libraries, or general-purpose tools or generally available free + programs which are used unmodified in performing those activities but + which are not part of the work. For example, Corresponding Source + includes interface definition files associated with source files for + the work, and the source code for shared libraries and dynamically + linked subprograms that the work is specifically designed to require, + such as by intimate data communication or control flow between those + subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users + can regenerate automatically from other parts of the Corresponding + Source.

+ +

The Corresponding Source for a work in source code form is that + same work.

+ +

2. Basic Permissions.

+ +

All rights granted under this License are granted for the term of + copyright on the Program, and are irrevocable provided the stated + conditions are met. This License explicitly affirms your unlimited + permission to run the unmodified Program. The output from running a + covered work is covered by this License only if the output, given its + content, constitutes a covered work. This License acknowledges your + rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not + convey, without conditions so long as your license otherwise remains + in force. You may convey covered works to others for the sole purpose + of having them make modifications exclusively for you, or provide you + with facilities for running those works, provided that you comply with + the terms of this License in conveying all material for which you do + not control copyright. Those thus making or running the covered works + for you must do so exclusively on your behalf, under your direction + and control, on terms that prohibit them from making any copies of + your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under + the conditions stated below. Sublicensing is not allowed; section 10 + makes it unnecessary.

+ +

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+ +

No covered work shall be deemed part of an effective technological + measure under any applicable law fulfilling obligations under article + 11 of the WIPO copyright treaty adopted on 20 December 1996, or + similar laws prohibiting or restricting circumvention of such + measures.

+ +

When you convey a covered work, you waive any legal power to forbid + circumvention of technological measures to the extent such circumvention + is effected by exercising rights under this License with respect to + the covered work, and you disclaim any intention to limit operation or + modification of the work as a means of enforcing, against the work's + users, your or third parties' legal rights to forbid circumvention of + technological measures.

+ +

4. Conveying Verbatim Copies.

+ +

You may convey verbatim copies of the Program's source code as you + receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice; + keep intact all notices stating that this License and any + non-permissive terms added in accord with section 7 apply to the code; + keep intact all notices of the absence of any warranty; and give all + recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, + and you may offer support or warranty protection for a fee.

+ +

5. Conveying Modified Source Versions.

+ +

You may convey a work based on the Program, or the modifications to + produce it from the Program, in the form of source code under the + terms of section 4, provided that you also meet all of these conditions:

+ +
    + +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices".
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • + +
+ +

A compilation of a covered work with other separate and independent + works, which are not by their nature extensions of the covered work, + and which are not combined with it such as to form a larger program, + in or on a volume of a storage or distribution medium, is called an + "aggregate" if the compilation and its resulting copyright are not + used to limit the access or legal rights of the compilation's users + beyond what the individual works permit. Inclusion of a covered work + in an aggregate does not cause this License to apply to the other + parts of the aggregate.

+ +

6. Conveying Non-Source Forms.

+ +

You may convey a covered work in object code form under the terms + of sections 4 and 5, provided that you also convey the + machine-readable Corresponding Source under the terms of this License, + in one of these ways:

+ +
    + +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • + +
+ +

A separable portion of the object code, whose source code is excluded + from the Corresponding Source as a System Library, need not be + included in conveying the object code work.

+ +

A "User Product" is either (1) a "consumer product", which means any + tangible personal property which is normally used for personal, family, + or household purposes, or (2) anything designed or sold for incorporation + into a dwelling. In determining whether a product is a consumer product, + doubtful cases shall be resolved in favor of coverage. For a particular + product received by a particular user, "normally used" refers to a + typical or common use of that class of product, regardless of the status + of the particular user or of the way in which the particular user + actually uses, or expects or is expected to use, the product. A product + is a consumer product regardless of whether the product has substantial + commercial, industrial or non-consumer uses, unless such uses represent + the only significant mode of use of the product.

+ +

"Installation Information" for a User Product means any methods, + procedures, authorization keys, or other information required to install + and execute modified versions of a covered work in that User Product from + a modified version of its Corresponding Source. The information must + suffice to ensure that the continued functioning of the modified object + code is in no case prevented or interfered with solely because + modification has been made.

+ +

If you convey an object code work under this section in, or with, or + specifically for use in, a User Product, and the conveying occurs as + part of a transaction in which the right of possession and use of the + User Product is transferred to the recipient in perpetuity or for a + fixed term (regardless of how the transaction is characterized), the + Corresponding Source conveyed under this section must be accompanied + by the Installation Information. But this requirement does not apply + if neither you nor any third party retains the ability to install + modified object code on the User Product (for example, the work has + been installed in ROM).

+ +

The requirement to provide Installation Information does not include a + requirement to continue to provide support service, warranty, or updates + for a work that has been modified or installed by the recipient, or for + the User Product in which it has been modified or installed. Access to a + network may be denied when the modification itself materially and + adversely affects the operation of the network or violates the rules and + protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, + in accord with this section must be in a format that is publicly + documented (and with an implementation available to the public in + source code form), and must require no special password or key for + unpacking, reading or copying.

+ +

7. Additional Terms.

+ +

"Additional permissions" are terms that supplement the terms of this + License by making exceptions from one or more of its conditions. + Additional permissions that are applicable to the entire Program shall + be treated as though they were included in this License, to the extent + that they are valid under applicable law. If additional permissions + apply only to part of the Program, that part may be used separately + under those permissions, but the entire Program remains governed by + this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option + remove any additional permissions from that copy, or from any part of + it. (Additional permissions may be written to require their own + removal in certain cases when you modify the work.) You may place + additional permissions on material, added by you to a covered work, + for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you + add to a covered work, you may (if authorized by the copyright holders of + that material) supplement the terms of this License with terms:

+ +
    + +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • + +
+ +

All other non-permissive additional terms are considered "further + restrictions" within the meaning of section 10. If the Program as you + received it, or any part of it, contains a notice stating that it is + governed by this License along with a term that is a further restriction, + you may remove that term. If a license document contains a further + restriction but permits relicensing or conveying under this License, you + may add to a covered work material governed by the terms of that license + document, provided that the further restriction does not survive such + relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the + form of a separately written license, or stated as exceptions; + the above requirements apply either way.

+ +

8. Termination.

+ +

You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights under + this License (including any patent licenses granted under the third + paragraph of section 11).

+ +

However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the copyright + holder fails to notify you of the violation by some reasonable means + prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from that + copyright holder, and you cure the violation prior to 30 days after + your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the + licenses of parties who have received copies or rights from you under + this License. If your rights have been terminated and not permanently + reinstated, you do not qualify to receive new licenses for the same + material under section 10.

+ +

9. Acceptance Not Required for Having Copies.

+ +

You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer transmission + to receive a copy likewise does not require acceptance. However, + nothing other than this License grants you permission to propagate or + modify any covered work. These actions infringe copyright if you do + not accept this License. Therefore, by modifying or propagating a + covered work, you indicate your acceptance of this License to do so.

+ +

10. Automatic Licensing of Downstream Recipients.

+ +

Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not responsible + for enforcing compliance by third parties with this License.

+ +

An "entity transaction" is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a covered + work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party's predecessor in interest had or could + give under the previous paragraph, plus a right to possession of the + Corresponding Source of the work from the predecessor in interest, if + the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you may + not impose a license fee, royalty, or other charge for exercise of + rights granted under this License, and you may not initiate litigation + (including a cross-claim or counterclaim in a lawsuit) alleging that + any patent claim is infringed by making, using, selling, offering for + sale, or importing the Program or any portion of it.

+ +

11. Patents.

+ +

A "contributor" is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. The + work thus licensed is called the contributor's "contributor version".

+ +

A contributor's "essential patent claims" are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, permitted + by this License, of making, using, or selling its contributor version, + but do not include claims that would be infringed only as a + consequence of further modification of the contributor version. For + purposes of this definition, "control" includes the right to grant + patent sublicenses in a manner consistent with the requirements of + this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free + patent license under the contributor's essential patent claims, to + make, use, sell, offer for sale, import and otherwise run, modify and + propagate the contents of its contributor version.

+ +

In the following three paragraphs, a "patent license" is any express + agreement or commitment, however denominated, not to enforce a patent + (such as an express permission to practice a patent or covenant not to + sue for patent infringement). To "grant" such a patent license to a + party means to make such an agreement or commitment not to enforce a + patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, + and the Corresponding Source of the work is not available for anyone + to copy, free of charge and under the terms of this License, through a + publicly available network server or other readily accessible means, + then you must either (1) cause the Corresponding Source to be so + available, or (2) arrange to deprive yourself of the benefit of the + patent license for this particular work, or (3) arrange, in a manner + consistent with the requirements of this License, to extend the patent + license to downstream recipients. "Knowingly relying" means you have + actual knowledge that, but for the patent license, your conveying the + covered work in a country, or your recipient's use of the covered work + in a country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, modify + or convey a specific copy of the covered work, then the patent license + you grant is automatically extended to all recipients of the covered + work and works based on it.

+ +

A patent license is "discriminatory" if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that are + specifically granted under this License. You may not convey a covered + work if you are a party to an arrangement with a third party that is + in the business of distributing software, under which you make payment + to the third party based on the extent of your activity of conveying + the work, and under which the third party grants, to any of the + parties who would receive the covered work from you, a discriminatory + patent license (a) in connection with copies of the covered work + conveyed by you (or copies made from those copies), or (b) primarily + for and in connection with specific products or compilations that + contain the covered work, unless you entered into that arrangement, + or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law.

+ +

12. No Surrender of Others' Freedom.

+ +

If conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot convey a + covered work so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you may + not convey it at all. For example, if you agree to terms that obligate you + to collect a royalty for further conveying from those to whom you convey + the Program, the only way you could satisfy both those terms and this + License would be to refrain entirely from conveying the Program.

+ +

13. Remote Network Interaction; Use with the GNU General Public License.

+ +

Notwithstanding any other provision of this License, if you modify the + Program, your modified version must prominently offer all users + interacting with it remotely through a computer network (if your version + supports such interaction) an opportunity to receive the Corresponding + Source of your version by providing access to the Corresponding Source + from a network server at no charge, through some standard or customary + means of facilitating copying of software. This Corresponding Source + shall include the Corresponding Source for any work covered by version 3 + of the GNU General Public License that is incorporated pursuant to the + following paragraph.

+ +

Notwithstanding any other provision of this License, you have permission + to link or combine any covered work with a work licensed under version 3 + of the GNU General Public License into a single combined work, and to + convey the resulting work. The terms of this License will continue to + apply to the part which is the covered work, but the work with which it is + combined will remain governed by version 3 of the GNU General Public + License.

+ +

14. Revised Versions of this License.

+ +

The Free Software Foundation may publish revised and/or new versions of + the GNU Affero General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may differ + in detail to address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU Affero + General Public License "or any later version" applies to it, you have + the option of following the terms and conditions either of that + numbered version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number + of the GNU Affero General Public License, you may choose any version + ever published by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future + versions of the GNU Affero General Public License can be used, that + proxy's public statement of acceptance of a version permanently + authorizes you to choose that version for the Program.

+ +

Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version.

+ +

15. Disclaimer of Warranty.

+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF + ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +

16. Limitation of Liability.

+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES.

+ +

17. Interpretation of Sections 15 and 16.

+ +

If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely approximates + an absolute waiver of all civil liability in connection with the + Program, unless a warranty or assumption of liability accompanies a + copy of the Program in return for a fee.

+ +

END OF TERMS AND CONDITIONS

+ +

How to Apply These Terms to Your New Programs

+ +

If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms.

+ +

To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + state the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found.

+ +
    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ +

Also add information on how to contact you by electronic and paper mail.

+ +

If your software can interact with users remotely through a computer + network, you should also make sure that it provides a way for users to + get its source. For example, if your program is a web application, its + interface could display a "Source" link that leads users to an archive + of the code. There are many ways you could offer source, and different + solutions will be better for different programs; see section 13 for the + specific requirements.

+ +

You should also get your employer (if you work as a programmer) or school, + if any, to sign a "copyright disclaimer" for the program, if necessary. + For more information on this, and how to apply and follow the GNU AGPL, see + <http://www.gnu.org/licenses/>.

diff --git a/src/octoprint/templates/dialogs/about.jinja2 b/src/octoprint/templates/dialogs/about.jinja2 new file mode 100644 index 00000000..832928ec --- /dev/null +++ b/src/octoprint/templates/dialogs/about.jinja2 @@ -0,0 +1,53 @@ + diff --git a/src/octoprint/templates/dialogs/about/about.jinja2 b/src/octoprint/templates/dialogs/about/about.jinja2 new file mode 100644 index 00000000..e207b363 --- /dev/null +++ b/src/octoprint/templates/dialogs/about/about.jinja2 @@ -0,0 +1,44 @@ +

{{ _('OctoPrint') }}

+ +

{{ _('The snappy web interface for your 3D printer') }}

+ +

Version {{ display_version }}

+ + + +

+ OctoPrint is sponsored and maintained by BQ. +

+ +

+ © 2012-{{ now.strftime("%Y") }} The OctoPrint Authors +

+ +

+ This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. +

+ +

+ For a copy of the GNU Affero General Public License, see "OctoPrint License" + to the left. +

+ +

+ OctoPrint also utilizes various dependencies under terms of their + respective licenses, which can be found under "Third Party Licenses" to + the left. Copyright of those dependencies lies with their respective authors +

diff --git a/src/octoprint/templates/dialogs/about/authors.jinja2 b/src/octoprint/templates/dialogs/about/authors.jinja2 new file mode 100644 index 00000000..42a59fe9 --- /dev/null +++ b/src/octoprint/templates/dialogs/about/authors.jinja2 @@ -0,0 +1 @@ +{% filter markdown %}{% filter offset_markdown_headers(2) %}{% include "_data/AUTHORS.md" ignore missing %}{% endfilter %}{% endfilter %} diff --git a/src/octoprint/templates/dialogs/about/changelog.jinja2 b/src/octoprint/templates/dialogs/about/changelog.jinja2 new file mode 100644 index 00000000..60c34b3a --- /dev/null +++ b/src/octoprint/templates/dialogs/about/changelog.jinja2 @@ -0,0 +1 @@ +{% filter markdown %}{% filter offset_markdown_headers(2) %}{% include "_data/CHANGELOG.md" ignore missing %}{% endfilter %}{% endfilter %} diff --git a/src/octoprint/templates/dialogs/about/license.jinja2 b/src/octoprint/templates/dialogs/about/license.jinja2 new file mode 100644 index 00000000..38848981 --- /dev/null +++ b/src/octoprint/templates/dialogs/about/license.jinja2 @@ -0,0 +1 @@ +{% include "_data/agpl.html" %} diff --git a/src/octoprint/templates/dialogs/about/thirdparty.jinja2 b/src/octoprint/templates/dialogs/about/thirdparty.jinja2 new file mode 100644 index 00000000..ab4e48e4 --- /dev/null +++ b/src/octoprint/templates/dialogs/about/thirdparty.jinja2 @@ -0,0 +1 @@ +{% filter markdown %}{% filter offset_markdown_headers(2) %}{% include "_data/THIRDPARTYLICENSES.md" ignore missing %}{% endfilter %}{% endfilter %} diff --git a/src/octoprint/templates/index.jinja2 b/src/octoprint/templates/index.jinja2 index 415734d9..5196d969 100644 --- a/src/octoprint/templates/index.jinja2 +++ b/src/octoprint/templates/index.jinja2 @@ -119,6 +119,7 @@
  • {{ _('Sourcecode') }}
  • {{ _('Documentation') }}
  • {{ _('Bugs and Requests') }}
  • + @@ -128,6 +129,7 @@ {% include 'dialogs/slicing.jinja2' %} {% include 'dialogs/usersettings.jinja2' %} {% include 'dialogs/wizard.jinja2' %} + {% include 'dialogs/about.jinja2' %} diff --git a/src/octoprint/util/__init__.py b/src/octoprint/util/__init__.py index 97ff4fb5..fb8c8f8c 100644 --- a/src/octoprint/util/__init__.py +++ b/src/octoprint/util/__init__.py @@ -372,6 +372,11 @@ def to_unicode(s_or_u, encoding="utf-8", errors="strict"): return s_or_u +def is_running_from_source(): + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) + return os.path.isdir(os.path.join(root, "src")) and os.path.isfile(os.path.join(root, "setup.py")) + + def dict_merge(a, b): """ Recursively deep-merges two dictionaries.