diff options
Diffstat (limited to 'pyload/web')
23 files changed, 414 insertions, 177 deletions
diff --git a/pyload/web/api_app.py b/pyload/web/api_app.py index 9370e671f..39747d5ea 100644 --- a/pyload/web/api_app.py +++ b/pyload/web/api_app.py @@ -13,6 +13,30 @@ from pyload.Api import ExceptionObject from pyload.remote.json_converter import loads, dumps, BaseEncoder from pyload.utils import remove_chars +# used for gzip compression +try: + import gzip + from cStringIO import StringIO +except ImportError: + gzip = None + StringIO = None + +# gzips response if supported +def json_response(obj): + accept = 'gzip' in request.headers.get('Accept-Encoding', '') + result = dumps(obj) + # don't compress small string + if gzip and accept and len(result) > 500: + response.headers['Vary'] = 'Accept-Encoding' + response.headers['Content-Encoding'] = 'gzip' + zbuf = StringIO() + zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) + zfile.write(result) + zfile.close() + return zbuf.getvalue() + + return result + # returns http error def error(code, msg): @@ -78,7 +102,7 @@ def call_api(func, args=""): result = getattr(api, func)(*args, **kwargs) # null is invalid json response if result is None: result = True - return dumps(result) + return json_response(result) except ExceptionObject, e: return error(400, e.message) @@ -98,7 +122,7 @@ def login(): user = PYLOAD.checkAuth(username, password, request.environ.get('REMOTE_ADDR', None)) if not user: - return dumps(False) + return json_response(False) s = set_session(request, user) @@ -116,7 +140,7 @@ def login(): if request.params.get('user', None): return dumps(result) - return dumps(sid) + return json_response(sid) @route("/api/logout") @@ -127,4 +151,4 @@ def logout(): s = request.environ.get('beaker.session') s.delete() - return dumps(True) + return json_response(True) diff --git a/pyload/web/app/index.html b/pyload/web/app/index.html index bf75d40ed..98e1bf233 100644 --- a/pyload/web/app/index.html +++ b/pyload/web/app/index.html @@ -80,29 +80,52 @@ <a href="http://pyload.org/" target="_blank">The pyLoad Team</a><br> </div> </div> - <div class="span2"> - <h2 class="block-title">Powered by</h2> + <div class="span2 block"> + <h2 class="block-title"> + <a href="http://pyload.org" target="_blank"> + Community <i class="icon-comment"></i> + </a> + </h2> <hr> - Bootstrap <br> + <a href="http://pyload.org" target="_blank">Homepage</a> · + <a href="http://board.pyload.org" target="_blank">Board</a> · + <a href="http://pyload.org/chat" target="_blank">Chat</a> </div> - <div class="span2"> - <h2 class="block-title">pyLoad</h2> + <div class="span2 block"> + <h2 class="block-title"> + <a href="https://twitter.com/pyload" target="_blank"> + Follow us <i class="icon-twitter"></i> + </a> + </h2> <hr> - dsfdsf <br> + <a href="https://twitter.com/pyload" target="_blank">Twitter</a> · + <a href="http://www.youtube.com/user/pyloadTeam" target="_blank">Youtube</a> </div> - <div class="span2"> - <h2 class="block-title">Community</h2> + <div class="span2 block"> + <h2 class="block-title"> + <a href="https://github.com/pyload" target="_blank"> + Development <i class="icon-github"></i> + </a> + </h2> <hr> - asd <br> + <a href="https://github.com/pyload" target="_blank">Github</a> · + <a href="http://docs.pyload.org" target="_blank">Documentation</a> </div> - <div class="span2"> - <h2 class="block-title">Development</h2> + <div class="span2 block"> + <h2 class="block-title"> + <a href="http://pyload.org/donate" target="_blank"> + Donate <i class="icon-bitcoin"> </i> + </a> + </h2> <hr> - asd <br> + <a href="http://pyload.org/donate" target="_blank">PayPal</a> · + <a href="http://blockchain.info/address/1JvcfSKuzk3VENJm9XtqGp2DCTesgokkG2" target="_blank">Bitcoin</a> · + <a href="https://flattr.com/profile/pyload" target="_blank">Flattr</a> </div> + </div> </div> </footer> diff --git a/pyload/web/app/scripts/models/Setup.js b/pyload/web/app/scripts/models/Setup.js index 82a2978db..424edf452 100644 --- a/pyload/web/app/scripts/models/Setup.js +++ b/pyload/web/app/scripts/models/Setup.js @@ -4,10 +4,30 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'], return Backbone.Model.extend({ + url: App.apiUrl('setup'), defaults: { lang: 'en', + system: null, + deps: null, user: null, password: null + }, + + fetch: function(options) { + options || (options = {}); + options.url = App.apiUrl('setup'); + return Backbone.Model.prototype.fetch.call(this, options); + }, + + // will get a 409 on success + submit: function(options) { + options || (options = {}); + options.url = App.apiUrl('setup_done'); + options.data = { + user: this.get('user'), + password: this.get('password') + }; + return Backbone.Model.prototype.fetch.call(this, options); } }); diff --git a/pyload/web/app/scripts/views/linkgrabber/packageView.js b/pyload/web/app/scripts/views/linkgrabber/packageView.js index 95c46e3cc..356d39b4b 100644 --- a/pyload/web/app/scripts/views/linkgrabber/packageView.js +++ b/pyload/web/app/scripts/views/linkgrabber/packageView.js @@ -39,9 +39,19 @@ define(['jquery', 'underscore', 'backbone', 'app', 'hbs!tpl/linkgrabber/package' return false; }, - renamePackage: function() { + renamePackage: function(e) { + e.stopPropagation(); + this.ui.name.addClass('edit'); this.ui.name.find('input').focus(); + + var self = this; + $(document).one('click', function() { + self.ui.name.removeClass('edit'); + self.ui.name.focus(); + }); + + return false; }, saveName: function(e) { diff --git a/pyload/web/app/scripts/views/setup/finishedView.js b/pyload/web/app/scripts/views/setup/finishedView.js new file mode 100644 index 000000000..9f0f8db19 --- /dev/null +++ b/pyload/web/app/scripts/views/setup/finishedView.js @@ -0,0 +1,25 @@ +define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/finished'], + function($, Backbone, _, App, template) { + 'use strict'; + + return Backbone.Marionette.ItemView.extend({ + + name: 'Finished', + template: template, + + events: { + 'click .btn-blue': 'confirm' + }, + + ui: { + }, + + onRender: function() { + }, + + confirm: function() { + this.model.submit(); + } + + }); + });
\ No newline at end of file diff --git a/pyload/web/app/scripts/views/setup/setupView.js b/pyload/web/app/scripts/views/setup/setupView.js index 7636a0bc2..8ab6fba51 100644 --- a/pyload/web/app/scripts/views/setup/setupView.js +++ b/pyload/web/app/scripts/views/setup/setupView.js @@ -1,6 +1,6 @@ -define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setup/layout', 'hbs!tpl/setup/actionbar', - './welcomeView', './systemView'], - function($, Backbone, _, App, Setup, template, templateBar, welcomeView, systemView) { +define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setup/layout', 'hbs!tpl/setup/actionbar', 'hbs!tpl/setup/error', + './welcomeView', './systemView', './userView', './finishedView'], + function($, Backbone, _, App, Setup, template, templateBar, templateError, welcomeView, systemView, userView, finishedView) { 'use strict'; return Backbone.Marionette.ItemView.extend({ @@ -15,11 +15,14 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setu pages: [ welcomeView, - systemView + systemView, + userView, + finishedView ], page: 0, view: null, + error: null, initialize: function() { var self = this; @@ -52,37 +55,66 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/Setup', 'hbs!tpl/setu }); this.listenTo(this.model, 'page:next', function() { - self.openPage(self.page++); + self.openPage(self.page + 1); }); this.listenTo(this.model, 'page:prev', function() { - self.openPage(self.page--); + self.openPage(self.page - 1); }); + + this.listenTo(this.model, 'error', this.onError); + this.model.fetch(); }, openPage: function(page) { console.log('Change page', page); // check if number is reasonable - if (!_.isNumber(page) || !_.isFinite(page)) + if (!_.isNumber(page) || !_.isFinite(page) || page < 0 || page >= this.pages.length) return; if (page === this.page) return; + // Render error directly + if (this.error) { + this.onRender(); + return; + } + this.page = page; - this.onRender(); + + var self = this; + this.ui.page.fadeOut({complete: function() { + self.onRender(); + }}); this.model.trigger('page:changed', page); }, + onError: function(model, xhr) { + console.log('Setup error', xhr); + this.error = xhr; + this.onRender(); + }, + onRender: function() { + // close old opened view if (this.view) this.view.close(); - // TODO: animation + // Render error if occurred + if (this.error) { + this.ui.page.html(templateError(this.error)); + return; + } + this.view = new this.pages[this.page]({model: this.model}); this.ui.page.empty(); - this.ui.page.append(this.view.render().$el); + + var el = this.view.render().el; + this.ui.page.append(el); + + this.ui.page.fadeIn(); } }); diff --git a/pyload/web/app/scripts/views/setup/systemView.js b/pyload/web/app/scripts/views/setup/systemView.js index 11e50213d..b4c0f7e12 100644 --- a/pyload/web/app/scripts/views/setup/systemView.js +++ b/pyload/web/app/scripts/views/setup/systemView.js @@ -8,12 +8,17 @@ define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/system'], template: template, events: { + 'click .btn-blue': 'nextPage' }, ui: { }, onRender: function() { + }, + + nextPage: function() { + this.model.trigger('page:next'); } }); diff --git a/pyload/web/app/scripts/views/setup/userView.js b/pyload/web/app/scripts/views/setup/userView.js new file mode 100644 index 000000000..95eaa0dc2 --- /dev/null +++ b/pyload/web/app/scripts/views/setup/userView.js @@ -0,0 +1,39 @@ +define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/user'], + function($, Backbone, _, App, template) { + 'use strict'; + + return Backbone.Marionette.ItemView.extend({ + + name: 'User', + template: template, + + events: { + 'click .btn-blue': 'submit' + }, + + ui: { + username: '#username', + password: '#password', + password2: '#password2' + }, + + onRender: function() { + }, + + submit: function() { + var pw = this.ui.password.val(); + var pw2 = this.ui.password2.val(); + + // TODO more checks and error messages + if (pw !== pw2) { + return; + } + + this.model.set('user', this.ui.username.val()); + this.model.set('password', pw); + + this.model.trigger('page:next'); + } + + }); + });
\ No newline at end of file diff --git a/pyload/web/app/scripts/views/setup/welcomeView.js b/pyload/web/app/scripts/views/setup/welcomeView.js index 4affc9075..a964e0d42 100644 --- a/pyload/web/app/scripts/views/setup/welcomeView.js +++ b/pyload/web/app/scripts/views/setup/welcomeView.js @@ -8,12 +8,17 @@ define(['jquery', 'backbone', 'underscore', 'app', 'hbs!tpl/setup/welcome'], template: template, events: { + 'click .btn-blue': 'nextPage' }, ui: { }, onRender: function() { + }, + + nextPage: function() { + this.model.trigger('page:next'); } }); diff --git a/pyload/web/app/styles/default/main.less b/pyload/web/app/styles/default/main.less index 6bf21e80b..6153b576e 100644 --- a/pyload/web/app/styles/default/main.less +++ b/pyload/web/app/styles/default/main.less @@ -13,10 +13,10 @@ @import "settings"; @import "accounts"; @import "admin"; +@import "setup"; @ResourcePath: "../.."; @DefaultFont: 'Abel', sans-serif; // Changed dimensions -@header-height: 70px; -@footer-height: 66px;
\ No newline at end of file +@header-height: 70px;;
\ No newline at end of file diff --git a/pyload/web/app/styles/default/setup.less b/pyload/web/app/styles/default/setup.less new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pyload/web/app/styles/default/setup.less diff --git a/pyload/web/app/styles/default/style.less b/pyload/web/app/styles/default/style.less index da0e68991..ad60e5b59 100644 --- a/pyload/web/app/styles/default/style.less +++ b/pyload/web/app/styles/default/style.less @@ -284,15 +284,4 @@ header { // background-color: @greyDark; border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; -} - -/* - Footer -*/ -footer .copyright { - background-size: 40px 40px; - background-position: 12px center; - height: 40px; - padding-left: 40px; - padding-top: 10px; -} +}
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/error.html b/pyload/web/app/templates/default/setup/error.html new file mode 100644 index 000000000..37ce51283 --- /dev/null +++ b/pyload/web/app/templates/default/setup/error.html @@ -0,0 +1,14 @@ +{{#ifEq status 410}} + <h2 class="text-warning">{{ _ "Setup timed out" }}</h2> + <p>{{ _ "Setup was closed due to inactivity. Please restart it to continue configuration." }}</p> +{{else}} +{{#ifEq status 409}} + <h2 class="text-success">{{ _ "Setup finished" }}</h2> + <p>{{ _ "Setup was successful. You can restart pyLoad now." }}</p> +{{else}} + <h2 class="text-error"> + {{ _ "Setup failed" }} + </h2> + <p>{{ _ "Try to restart it or open a bug report." }}</p> +{{/ifEq}} +{{/ifEq}}
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/finished.html b/pyload/web/app/templates/default/setup/finished.html new file mode 100644 index 000000000..22a97649b --- /dev/null +++ b/pyload/web/app/templates/default/setup/finished.html @@ -0,0 +1,23 @@ +{{#if user}} + +<h2> + {{ _ "Nearly Done" }} +</h2> + +<p> + {{ _ "Please check your settings." }} +</p> + +<p> + <strong>Username:</strong> {{user}} +</p> + +<button class="btn btn-large btn-blue"> + {{ _ "Confirm" }} +</button> + +{{else}} + +<h2>{{ _ "Please add a user first." }}</h2> + +{{/if}} diff --git a/pyload/web/app/templates/default/setup/layout.html b/pyload/web/app/templates/default/setup/layout.html index 7b75e53b1..2e986173a 100644 --- a/pyload/web/app/templates/default/setup/layout.html +++ b/pyload/web/app/templates/default/setup/layout.html @@ -3,5 +3,8 @@ {{ _ "Setup" }} </h1> </div> -<div class="span8 setup-page"> +<div class="span8"> + <div class="hero-unit setup-page"> + + </div> </div>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/system.html b/pyload/web/app/templates/default/setup/system.html index 84a217b19..0c5023669 100644 --- a/pyload/web/app/templates/default/setup/system.html +++ b/pyload/web/app/templates/default/setup/system.html @@ -1,5 +1,56 @@ -<h1>{{ _ "System" }} </h1> +<h3>{{ _ "System" }} </h3> -<h2>{{_ "Dependencies" }}</h2> +<dl class="dl-horizontal"> + {{#each system}} + <dt>{{ @key }}</dt> + <dd>{{ this }}</dd> + {{/each}} +</dl> -<h2>{{ _ "Optional" }}</h2>
\ No newline at end of file +<h3>{{_ "Dependencies" }}</h3> +<dl class="dl-horizontal"> + {{#each deps.core}} + <dt>{{ name }}</dt> + <dd> + {{#if avail}} + <span class="text-success"> + <i class="icon-ok"></i> + {{#if v}} + ({{v}}) + {{/if}} + </span> + {{else}} + <span class="text-error"> + <i class="icon-remove"></i> + </span> + {{/if}} + </dd> + {{/each}} +</dl> + + +<h4>{{ _ "Optional" }}</h4> +<dl class="dl-horizontal"> + {{#each deps.opt}} + <dt>{{ name }}</dt> + <dd> + {{#if avail}} + <span class="text-success"> + {{ _ "available" }} + {{#if v}} + ({{v}}) + {{/if}} + </span> + {{else}} + <span class="text-error"> + {{ _ "not available" }} + </span> + {{/if}} + </dd> + {{/each}} +</dl> + + +<button class="btn btn-blue"> + {{ _ "Next" }} +</button>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/user.html b/pyload/web/app/templates/default/setup/user.html new file mode 100644 index 000000000..fe3f2de71 --- /dev/null +++ b/pyload/web/app/templates/default/setup/user.html @@ -0,0 +1,34 @@ +<form class="form-horizontal"> + <div class="control-group"> + <label class="control-label"> + Username + </label> + + <div class="controls"> + <input type="text" id="username" placeholder="User"> + </div> + </div> + <div class="control-group"> + <label class="control-label"> + Password + </label> + + <div class="controls"> + <input type="password" id="password"> + </div> + </div> + <div class="control-group"> + <label class="control-label"> + Password (again) + </label> + + <div class="controls"> + <input type="password" id="password2"> + </div> + </div> + <div class="control-group"> + <div class="controls"> + <a class="btn btn-blue">Submit</a> + </div> + </div> +</form>
\ No newline at end of file diff --git a/pyload/web/app/templates/default/setup/welcome.html b/pyload/web/app/templates/default/setup/welcome.html index f5c5af4d7..5a4f74d9f 100644 --- a/pyload/web/app/templates/default/setup/welcome.html +++ b/pyload/web/app/templates/default/setup/welcome.html @@ -1,16 +1,14 @@ -<div class="hero-unit"> - <h1>{{ _ "Welcome!" }}</h1> +<h1>{{ _ "Welcome!" }}</h1> - <p>{{ _ "pyLoad is running and ready for configuration." }}</p> +<p>{{ _ "pyLoad is running and ready for configuration." }}</p> - <p> - {{ _ "Select your language:" }} - <select> - <option>en</option> - </select> - </p> +<p> + {{ _ "Select your language:" }} + <select> + <option>en</option> + </select> +</p> - <button class="btn btn-large btn-blue"> - {{ _ "Start configuration" }} - </button> -</div>
\ No newline at end of file +<button class="btn btn-large btn-blue"> + {{ _ "Start configuration" }} +</button>
\ No newline at end of file diff --git a/pyload/web/bower.json b/pyload/web/bower.json index b0176a891..4da3634a0 100644 --- a/pyload/web/bower.json +++ b/pyload/web/bower.json @@ -11,7 +11,7 @@ "jquery.cookie": "~1.3.1", "jquery.animate-enhanced": "*", "flot": "~0.8.1", - "underscore": "~1.4.4", + "underscore": "~1.5.1", "backbone": "~1.0.0", "backbone.marionette": "~1.1.0", "handlebars.js": "1.0.0-rc.3", diff --git a/pyload/web/middlewares.py b/pyload/web/middlewares.py index 074681b8f..af355bf11 100644 --- a/pyload/web/middlewares.py +++ b/pyload/web/middlewares.py @@ -1,17 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# gzip is optional on some platform -try: - import gzip -except ImportError: - gzip = None - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - class StripPathMiddleware(object): def __init__(self, app): self.app = app @@ -31,105 +20,3 @@ class PrefixMiddleware(object): if path.startswith(self.prefix): e['PATH_INFO'] = path.replace(self.prefix, "", 1) return self.app(e, h) - -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -# WSGI middleware -# Gzip-encodes the response. - -# TODO: not in use anymore, because of pre-gzipped resources -class GZipMiddleWare(object): - - def __init__(self, application, compress_level=6): - self.application = application - self.compress_level = int(compress_level) - - def __call__(self, environ, start_response): - if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): - # nothing for us to do, so this middleware will - # be a no-op: - return self.application(environ, start_response) - response = GzipResponse(start_response, self.compress_level) - app_iter = self.application(environ, - response.gzip_start_response) - if app_iter is not None: - response.finish_response(app_iter) - - return response.write() - -def header_value(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - return value - -def update_header(headers, key, value): - remove_header(headers, key) - headers.append((key, value)) - -def remove_header(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - headers.remove((header, value)) - break - -class GzipResponse(object): - - def __init__(self, start_response, compress_level): - self.start_response = start_response - self.compress_level = compress_level - self.buffer = StringIO() - self.compressible = False - self.content_length = None - self.headers = () - - def gzip_start_response(self, status, headers, exc_info=None): - self.headers = headers - ct = header_value(headers,'content-type') - ce = header_value(headers,'content-encoding') - cl = header_value(headers, 'content-length') - - # don't compress on unknown size, it may be too huge - cl = int(cl) if cl else 0 - - if ce: - self.compressible = False - elif gzip is not None and ct and (ct.startswith('text/') or ct.startswith('application/')) \ - and 'zip' not in ct and 200 < cl < 1024*1024: - self.compressible = True - headers.append(('content-encoding', 'gzip')) - headers.append(('vary', 'Accept-Encoding')) - - remove_header(headers, 'content-length') - self.headers = headers - self.status = status - return self.buffer.write - - def write(self): - out = self.buffer - out.seek(0) - s = out.getvalue() - out.close() - return [s] - - def finish_response(self, app_iter): - if self.compressible: - output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level, - fileobj=self.buffer) - else: - output = self.buffer - try: - for s in app_iter: - output.write(s) - if self.compressible: - output.close() - finally: - if hasattr(app_iter, 'close'): - try: - app_iter.close() - except : - pass - - content_length = self.buffer.tell() - update_header(self.headers, "Content-Length" , str(content_length)) - self.start_response(self.status, self.headers)
\ No newline at end of file diff --git a/pyload/web/pyload_app.py b/pyload/web/pyload_app.py index 1ec7cf4c9..1c89e2ada 100644 --- a/pyload/web/pyload_app.py +++ b/pyload/web/pyload_app.py @@ -70,7 +70,11 @@ def index(): # set variable depending on setup mode setup = 'false' if SETUP is None else 'true' ws = PYLOAD.getWSAddress() if PYLOAD else False - web = PYLOAD.getConfigValue('webinterface', 'port') if PYLOAD else False + web = None + if PYLOAD: + web = PYLOAD.getConfigValue('webinterface', 'port') + elif SETUP: + web = SETUP.config['webinterface']['port'] # Render variables into the html page if resp.status_code == 200: diff --git a/pyload/web/setup_app.py b/pyload/web/setup_app.py index 5163f9cc6..939fcb600 100644 --- a/pyload/web/setup_app.py +++ b/pyload/web/setup_app.py @@ -3,26 +3,71 @@ from time import time +from pyload.utils import json_dumps + from bottle import route, request, response, HTTPError, redirect from webinterface import PROJECT_DIR, SETUP from utils import add_json_header +# returns http error +def error(code, msg): + return HTTPError(code, json_dumps(msg), **dict(response.headers)) + + def setup_required(func): def _view(*args, **kwargs): + global timestamp + # setup needs to be running if SETUP is None: - redirect("/nopermission") + return error(404, "Not Found") + + # setup finished + if timestamp == 0: + return error(409, "Done") + + # setup timed out due to inactivity + if timestamp + TIMEOUT * 60 < time(): + return error(410, "Timeout") + + timestamp = time() return func(*args, **kwargs) + return _view # setup will close after inactivity TIMEOUT = 15 timestamp = time() + @route("/setup") @setup_required def setup(): - pass # TODO + add_json_header(response) + + return json_dumps({ + "system": SETUP.check_system(), + "deps": SETUP.check_deps() + }) + + +@route("/setup_done") +@setup_required +def setup_done(): + global timestamp + add_json_header(response) + + SETUP.addUser( + request.params['user'], + request.params['password'] + ) + + SETUP.save() + + # mark setup as finished + timestamp = 0 + + return error(409, "Done") diff --git a/pyload/web/utils.py b/pyload/web/utils.py index e94089185..7e8ee3f13 100644 --- a/pyload/web/utils.py +++ b/pyload/web/utils.py @@ -4,14 +4,21 @@ import re from bottle import request, HTTPError, redirect +try: + import zlib +except ImportError: + zlib = None + from webinterface import PYLOAD, SETUP + def add_json_header(r): r.headers.replace("Content-type", "application/json") r.headers.append("Cache-Control", "no-cache, must-revalidate") r.headers.append("Access-Control-Allow-Origin", request.get_header('Origin', '*')) r.headers.append("Access-Control-Allow-Credentials", "true") + def set_session(request, user): s = request.environ.get('beaker.session') s["uid"] = user.uid @@ -58,15 +65,14 @@ def is_mobile(): return True return False -def select_language(langs): +def select_language(langs): accept = request.headers.get('Accept-Language', '') # TODO return langs[0] - def login_required(perm=None): def _dec(func): def _view(*args, **kwargs): |