diff options
-rw-r--r-- | module/Setup.py (renamed from module/setup/Setup.py) | 193 | ||||
-rw-r--r-- | module/UserManager.py | 23 | ||||
-rw-r--r-- | module/network/HTTPDownload.py | 6 | ||||
-rw-r--r-- | module/setup/Questions.py | 50 | ||||
-rw-r--r-- | module/setup/__init__.py | 0 | ||||
-rw-r--r-- | module/utils/fs.py | 8 | ||||
-rw-r--r-- | module/web/ServerThread.py | 84 | ||||
-rw-r--r-- | module/web/setup_app.py | 13 | ||||
-rw-r--r-- | module/web/utils.py | 7 | ||||
-rwxr-xr-x | pyLoadCore.py | 11 |
10 files changed, 154 insertions, 241 deletions
diff --git a/module/setup/Setup.py b/module/Setup.py index 58506d8c2..4e89ed0f2 100644 --- a/module/setup/Setup.py +++ b/module/Setup.py @@ -1,144 +1,88 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -""" - 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 <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" -from getpass import getpass + +############################################################################### +# Copyright(c) 2008-2012 pyLoad Team +# http://www.pyload.org +# +# This file is part of pyLoad. +# pyLoad 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. +# +# Subjected to the terms and conditions in LICENSE +# +# @author: RaNaN +############################################################################### + import module.common.pylgettext as gettext import os -from os import makedirs -from os.path import abspath, dirname, exists, join -from subprocess import PIPE, call import sys +import socket +import webbrowser + +from getpass import getpass +from time import time from sys import exit + +from module.utils.fs import abspath, dirname, exists, join, makedirs from module.utils import get_console_encoding -from module.setup.System_Checks import System_Checks -from module.setup.Questions import Questions, Ask +from module.web.ServerThread import WebServer + + class Setup(): """ - pyLoads initial setup configuration assistent + pyLoads initial setup configuration assistant """ def __init__(self, path, config): self.path = path self.config = config self.stdin_encoding = get_console_encoding(sys.stdin.encoding) + self.lang = None + # We will create a timestamp so that the setup will be completed in a specific interval + self.timestamp = time() + + # TODO: probably unneeded self.yes = "yes" self.no = "no" - self.lang = None - self.page = 0 - - + + def start(self): + web = WebServer(pysetup=self) + web.start() + + error = web.check_error() + if error: #todo errno 44 port already in use + print error + + url = "http://%s:%d/" % (socket.gethostbyname(socket.gethostname()), web.port) + + print "Setup is started" + + opened = webbrowser.open_new_tab(url) + if not opened: + print "Please point your browser to %s" % url + + self.ask_lang() - checker = System_Checks() - result_s, result_b = checker.check_basic() - if not result_b: - print result_s - + print "" print _("Would you like to configure pyLoad via Webinterface?") print _("You need a Browser and a connection to this PC for it.") print _("Url would be: http://hostname:8000/") - viaweb = self.ask_cli(_("Start initial webinterface for configuration?"), self.yes, bool=True) + viaweb = self.ask(_("Start initial webinterface for configuration?"), self.yes, bool=True) if viaweb: self.start_web() else: self.start_cli() - def ask_lang(self): - if self.lang == None: - langs = self.config.getMetaData("general", "language").type.split(";") - self.lang = self.ask_cli(u"Choose your Language / Wähle deine Sprache", "en", langs) - gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) - translation = gettext.translation("setup", join(self.path, "locale"), languages=[self.lang, "en"], fallback=True) - translation.install(True) - - #l10n Input shorthand for yes - self.yes = _("y") - #l10n Input shorthand for no - self.no = _("n") - - def get_page_next(self): - self.__print_start() - if self.page == 0: - # system check - self.basic, self.ssl, self.captcha, self.web, self.js = self.system_check() - if not basic: - self.__print( _("You need pycurl, sqlite and python 2.5, 2.6 or 2.7 to run pyLoad.")) - self.__print( _("Please correct this and re-run pyLoad.")) - self.__print( _("Setup will now close.")) - self.__print_end() - return False - self.__print("") - self.__print(_("## Status ##")) - self.__print("") - - avail = [] - if self.check_module("Crypto"): avail.append(_("container decrypting")) - if ssl: avail.append(_("ssl connection")) - if captcha: avail.append(_("automatic captcha decryption")) - if web: avail.append(_("Webinterface")) - if js: avail.append(_("extended Click'N'Load")) - - string = "" - for av in avail: - string += ", " + av - # List available Features - self.__print(_("Features available:") + string[1:]) - self.__print("") - - return self.printer - - def __print(self, text): - if self.web == True: - self.printer += "<br />" + text - else: - print text - - def __print_start(self): - if self.web == True: - self.printer = "" - else: - print "" - - def __print_end(self): - if self.web == True: - self.printer = "" - else: - raw_input() - - def ask(self, qst, default, answers=[], bool=False, password=False): - if self.web == True: - self.ask_web(qst, default, answers, bool, password) - else: - self.ask_cli(qst, default, answers, bool, password) - def start_cli(self): - for ask in Questions.questions: - if ask.webonly: continue - for line in ask.sqt: - print line - if default == None: - raw_input() - print _("Welcome to the pyLoad Configuration Assistent.") print _("It will check your system and make a basic setup in order to run pyLoad.") print "" @@ -155,10 +99,6 @@ class Setup(): #self.get_page_next() - - - - if len(avail) < 5: print _("Features missing: ") print @@ -226,8 +166,8 @@ class Setup(): print _("Hit enter to exit and restart pyLoad") raw_input() return True - - + + def start_web(self): print "" print _("Webinterface running for setup.") @@ -245,7 +185,6 @@ class Setup(): self.start_cli() - def conf_basic(self): print "" print _("## Basic Setup ##") @@ -294,7 +233,6 @@ class Setup(): self.config["webinterface"]["port"] = self.ask(_("Port"), "8000") print "" print _("pyLoad offers several server backends, now following a short explanation.") - print "builtin:", _("laggy, but useful if RAM ") print "threaded:", _("Default server, this server offers SSL and is a good alternative to builtin.") print "fastcgi:", _( "Can be used by apache, lighttpd, requires you to configure them, which is not too easy job.") @@ -398,11 +336,21 @@ class Setup(): print _("Setting config path failed: %s") % str(e) + def ask_lang(self): + langs = self.config.getMetaData("general", "language").type.split(";") + self.lang = self.ask(u"Choose your Language / Wähle deine Sprache", "en", langs) + gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) + translation = gettext.translation("setup", join(self.path, "locale"), languages=[self.lang, "en"], fallback=True) + translation.install(True) + #l10n Input shorthand for yes + self.yes = _("y") + #l10n Input shorthand for no + self.no = _("n") + def ask(self, qst, default, answers=[], bool=False, password=False): + """ Generate dialog on command line """ - - def ask_cli(self, qst, default, answers=[], bool=False, password=False): if answers: info = "(" for i, answer in enumerate(answers): @@ -436,14 +384,9 @@ class Setup(): return p1 else: print _("Passwords did not match.") - - while True: - try: - input = raw_input(qst + " %s: " % info) - except KeyboardInterrupt: - print "\nSetup interrupted" - exit() + while True: + input = raw_input(qst + " %s: " % info) input = input.decode(self.stdin_encoding) if input.strip() == "": diff --git a/module/UserManager.py b/module/UserManager.py deleted file mode 100644 index 9d5e8c5db..000000000 --- a/module/UserManager.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - 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 <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" - -class UserManager: - """ - Manager class to handle all user related stuff - """
\ No newline at end of file diff --git a/module/network/HTTPDownload.py b/module/network/HTTPDownload.py index 5a4436529..498cd5979 100644 --- a/module/network/HTTPDownload.py +++ b/module/network/HTTPDownload.py @@ -205,6 +205,7 @@ class HTTPDownload(): t = time() # reduce these calls + # when num_q is 0, the loop is exited while lastFinishCheck + 0.5 < t: # list of failed curl handles failed = [] @@ -240,10 +241,10 @@ class HTTPDownload(): ex = e else: chunksDone.add(curl) - if not num_q: # no more infos to get + if not num_q: # no more info to get # check if init is not finished so we reset download connections - # note that other chunks are closed and downloaded with init too + # note that other chunks are closed and everything downloaded with initial connection if failed and init not in failed and init.c not in chunksDone: self.log.error(_("Download chunks failed, fallback to single connection | %s" % (str(ex)))) @@ -288,7 +289,6 @@ class HTTPDownload(): if self.abort: raise Abort() - #sleep(0.003) #suppress busy waiting - limits dl speed to (1 / x) * buffersize self.m.select(1) for chunk in self.chunks: diff --git a/module/setup/Questions.py b/module/setup/Questions.py deleted file mode 100644 index 08bff8deb..000000000 --- a/module/setup/Questions.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - 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 <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" -from getpass import getpass -import module.common.pylgettext as gettext -import os -from os import makedirs -from os.path import abspath, dirname, exists, join -from subprocess import PIPE, call -import sys -from sys import exit -from module.utils import get_console_encoding - -class Questions(): - - questions = [ - Ask(["Welcome to the pyLoad Configuration Assistent.", - "It will check your system and make a basic setup in order to run pyLoad.", - "If you don't know which value to choose, take the deafault one.", - "Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyLoadCore."]), - Ask(["The value in brackets [] always is the default value", - "When you are ready, hit Enter"], clionly=True) - - ] - - -class Ask(): - def __init__(self, qst, default = None, answers=[], bool=False, password=False, webonly=False, clionly=False): - self.qst = qst - self.default = default - self.answers = answers - self.bool = bool - self. password = password - - diff --git a/module/setup/__init__.py b/module/setup/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/module/setup/__init__.py +++ /dev/null diff --git a/module/utils/fs.py b/module/utils/fs.py index 1894bc49a..92cc605e7 100644 --- a/module/utils/fs.py +++ b/module/utils/fs.py @@ -26,6 +26,12 @@ def chmod(path, mode): except : pass +def dirname(path): + return fs_decode(os.path.dirname(fs_encode(path))) + +def abspath(path): + return fs_decode(os.path.abspath(fs_encode(path))) + def chown(path, uid, gid): return os.chown(fs_encode(path), uid, gid) @@ -40,7 +46,7 @@ def makedirs(path, mode=0755): # fs_decode? def listdir(path): - return os.listdir(fs_encode(path)) + return [fs_decode(x) for x in os.listdir(fs_encode(path))] def save_filename(name): #remove some chars diff --git a/module/web/ServerThread.py b/module/web/ServerThread.py index bf5ba8373..b4854e1f4 100644 --- a/module/web/ServerThread.py +++ b/module/web/ServerThread.py @@ -1,32 +1,43 @@ #!/usr/bin/env python from __future__ import with_statement -from os.path import exists +from time import time, sleep -import os import threading import logging +from module.utils.fs import exists + core = None setup = None log = logging.getLogger("log") class WebServer(threading.Thread): - def __init__(self, pycore): - global core + def __init__(self, pycore=None, pysetup=None): + global core, setup threading.Thread.__init__(self) - self.core = pycore - core = pycore - self.running = True - self.server = pycore.config['webinterface']['server'] - self.https = pycore.config['webinterface']['https'] - self.cert = pycore.config["ssl"]["cert"] - self.key = pycore.config["ssl"]["key"] - self.host = pycore.config['webinterface']['host'] - self.port = pycore.config['webinterface']['port'] + + if pycore: + core = pycore + config = pycore.config + elif pysetup: + setup = pysetup + config = pysetup.config + else: + raise Exception("No config context provided") + + self.server = config['webinterface']['server'] + self.https = config['webinterface']['https'] + self.cert = config["ssl"]["cert"] + self.key = config["ssl"]["key"] + self.host = config['webinterface']['host'] + self.port = config['webinterface']['port'] + self.error = None self.setDaemon(True) def run(self): + self.running = True + import webinterface global webinterface @@ -56,42 +67,47 @@ class WebServer(threading.Thread): if self.server == "builtin": self.server = "threaded" - if self.server == "fastcgi": - self.start_fcgi() - elif self.server == "threaded": - self.start_threaded() - elif self.server == "lightweight": - self.start_lightweight() - else: - self.start_fallback() + try: + if self.server == "fastcgi": + self.start_fcgi() + elif self.server == "threaded": + self.start_threaded() + elif self.server == "lightweight": + self.start_lightweight() + else: + self.start_fallback() + except Exception, e: + log.error(_("Failed starting webserver: " + e.message)) + self.error = e + if core: + core.print_exc() def start_fallback(self): - if self.https: log.warning(_("This server offers no SSL, please consider using threaded instead")) - self.core.log.info(_("Starting builtin webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) + log.info(_("Starting builtin webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) webinterface.run_simple(host=self.host, port=self.port) def start_threaded(self): if self.https: - self.core.log.info(_("Starting threaded SSL webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) + log.info(_("Starting threaded SSL webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) else: self.cert = "" self.key = "" - self.core.log.info(_("Starting threaded webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) + log.info(_("Starting threaded webserver: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) webinterface.run_threaded(host=self.host, port=self.port, cert=self.cert, key=self.key) def start_fcgi(self): - from flup.server.threadedserver import ThreadedServer + def noop(*args, **kwargs): pass ThreadedServer._installSignalHandlers = noop - self.core.log.info(_("Starting fastcgi server: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) + log.info(_("Starting fastcgi server: %(host)s:%(port)d") % {"host": self.host, "port": self.port}) webinterface.run_fcgi(host=self.host, port=self.port) @@ -99,8 +115,16 @@ class WebServer(threading.Thread): if self.https: log.warning(_("This server offers no SSL, please consider using threaded instead")) - self.core.log.info(_("Starting lightweight webserver (bjoern): %(host)s:%(port)d") % {"host": self.host, "port": self.port}) + log.info( + _("Starting lightweight webserver (bjoern): %(host)s:%(port)d") % {"host": self.host, "port": self.port}) webinterface.run_lightweight(host=self.host, port=self.port) - def quit(self): - self.running = False + + # check if an error was raised for n seconds + def check_error(self, n=1): + t = time() + n + while time() < t: + if self.error: + return self.error + sleep(0.1) + diff --git a/module/web/setup_app.py b/module/web/setup_app.py index 055cb2a81..68da474bb 100644 --- a/module/web/setup_app.py +++ b/module/web/setup_app.py @@ -1,13 +1,24 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from bottle import route, request, response, HTTPError +from bottle import route, request, response, HTTPError, redirect from webinterface import PROJECT_DIR, SETUP, env from utils import render_to_response +def setup_required(func): + def _view(*args, **kwargs): + + # setup needs to be running + if SETUP is None: + redirect("/nopermission") + + return func(*args, **kwargs) + return _view + @route("/setup") +@setup_required def setup(): return render_to_response('setup.html') diff --git a/module/web/utils.py b/module/web/utils.py index ba6a6a59e..236a9244e 100644 --- a/module/web/utils.py +++ b/module/web/utils.py @@ -19,7 +19,7 @@ import re from bottle import request, HTTPError, redirect, ServerAdapter -from webinterface import env, TEMPLATE, PYLOAD +from webinterface import env, TEMPLATE, PYLOAD, SETUP # TODO: useful but needs a rewrite, too def render_to_response(name, args={}, proc=[]): @@ -75,6 +75,11 @@ def is_mobile(): def login_required(perm=None): def _dec(func): def _view(*args, **kwargs): + + # In case of setup, no login methods can be accessed + if SETUP is not None: + redirect("/setup") + s = request.environ.get('beaker.session') api = get_user_api(s) if api is not None: diff --git a/pyLoadCore.py b/pyLoadCore.py index f005d9208..21d6603e5 100755 --- a/pyLoadCore.py +++ b/pyLoadCore.py @@ -117,24 +117,21 @@ class Core(object): elif option in ("-d", "--debug"): self.doDebug = True elif option in ("-u", "--user"): - from module.setup.Setup import Setup + from module.Setup import Setup self.config = ConfigParser() s = Setup(pypath, self.config) s.set_user() exit() elif option in ("-s", "--setup"): - from module.setup.Setup import Setup + from module.Setup import Setup self.config = ConfigParser() s = Setup(pypath, self.config) - if argument == "web": - s.start_web() - else: - s.start() + s.start() exit() elif option == "--changedir": - from module.setup.Setup import Setup + from module.Setup import Setup self.config = ConfigParser() s = Setup(pypath, self.config) |