diff options
| author | 2010-03-30 17:51:38 +0200 | |
|---|---|---|
| committer | 2010-03-30 17:51:38 +0200 | |
| commit | 4a99e86c462e09e3e050a9e0204e602ce8ebe30b (patch) | |
| tree | 932dbe90a9c852a45b783efaf13eb811997d73fe /module | |
| parent | fixes #64 (diff) | |
| download | pyload-4a99e86c462e09e3e050a9e0204e602ce8ebe30b.tar.xz | |
configuration assistent, some fixes
Diffstat (limited to 'module')
| -rw-r--r-- | module/XMLConfigParser.py | 18 | ||||
| -rw-r--r-- | module/config/core_default.xml | 2 | ||||
| -rw-r--r-- | module/setup.py | 370 | ||||
| -rw-r--r-- | module/web/ServerThread.py | 27 | 
4 files changed, 397 insertions, 20 deletions
| diff --git a/module/XMLConfigParser.py b/module/XMLConfigParser.py index 0aede384c..87b863d28 100644 --- a/module/XMLConfigParser.py +++ b/module/XMLConfigParser.py @@ -20,7 +20,7 @@ from __future__ import with_statement  from os.path import exists  from xml.dom.minidom import parse - +import re  from shutil import copy  class XMLConfigParser(): @@ -42,7 +42,7 @@ class XMLConfigParser():          file = self.file          if self.forceDefault:              file = self.file_default -        if not exists(self.file) and self.forceDefault: +        if not exists(self.file) or self.forceDefault:              self._copyConfig()          with open(file, 'r') as fh:              self.xml = parse(fh) @@ -117,7 +117,10 @@ class XMLConfigParser():      def getConfigDict(self):          return self.config -         + +    def getDataDict(self): +        return self.data +      def set(self, section, data, value):          root = self.root          replace = False @@ -213,7 +216,6 @@ class XMLConfigParser():      def checkInput(self, section, option, value):          oinput = self.getInputValues(section, option) -        print oinput          if oinput:              for i in oinput:                  if i == value: @@ -222,13 +224,13 @@ class XMLConfigParser():          otype = self.getType(section, option)          if not otype:              return True -        if otype == "int" and (type(value) == int or re.match("^\d+$")): +        if otype == "int" and (type(value) == int or re.match("^\d+$", value)):              return True -        elif otype == "bool" and (type(value) == bool or re.match("^(true|false|True|False)$")): +        elif otype == "bool" and (type(value) == bool or re.match("^(true|false|True|False)$", value)):              return True -        elif otype == "time" and re.match("^[0-2]{0,1}\d:[0-5]{0,1}\d$"): +        elif otype == "time" and re.match("^[0-2]{0,1}\d:[0-5]{0,1}\d$", value):              return True -        elif otype == "ip" and re.match("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"): +        elif otype == "ip" and re.match("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", value):              return True          elif otype == "str":              return True diff --git a/module/config/core_default.xml b/module/config/core_default.xml index 4925c06cf..d1c059060 100644 --- a/module/config/core_default.xml +++ b/module/config/core_default.xml @@ -31,7 +31,7 @@          <log_count type="int" name="Count">5</log_count>      </log>      <general name="General"> -        <language type="str" input="en;de;fr" name="Language">de</language> +        <language type="str" input="en;de;fr;nl;pl" name="Language">de</language>          <download_folder type="str" name="Download Folder">Downloads</download_folder>          <max_downloads type="int" name="Max Parallel Downloads">3</max_downloads>          <link_file type="str" name="File For Links">links.txt</link_file> diff --git a/module/setup.py b/module/setup.py new file mode 100644 index 000000000..a5d4db118 --- /dev/null +++ b/module/setup.py @@ -0,0 +1,370 @@ +#!/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 gettext +from hashlib import sha1 +from os import remove +from os.path import abspath +from os.path import dirname +from os.path import isfile +from os.path import join +import random +import re +from subprocess import PIPE +from subprocess import call +import sys + +class Setup(): +    """ +    pyLoads initial setup configuration assistent +    """ +    def __init__(self, path, config): + +        self.path = path +        self.config = config + + +    def start(self): +         +        lang = self.ask("Choose your Language / Wähle deine Sprache", "en", ["en", "de"]) +        translation = gettext.translation("setup", join(self.path, "locale"), languages=[lang]) +        translation.install(unicode=(True if  sys.getfilesystemencoding().startswith("utf") else False)) + +        print "" +        print _("Welcome to the pyLoad Configuration Assistent.") +        print _("It will check your system and make a basic setup in order to run pyLoad.") +        print "" +        print _("The value in brackets [] always is the default value,") +        print _("in case you don't want to change it or you are unsure what to choose, just hit enter.") +        print _("Don't forget: You can always rerun this assistent with --setup or -s parameter, when you start pyLoadCore.") +        print _("If you have any problems with this assistent hit STRG-C,") +        print _("to abort and don't let him start with pyLoadCore automatically anymore.") +        print "" +        print _("When you are ready for system check, hit enter.") +        raw_input() + +        basic, ssl, captcha, gui, web = self.system_check() +        print "" + +        if not basic: +            print _("You need pycurl and python 2.5 or 2.6 to run pyLoad.") +            print _("Please correct this and re run pyLoad.") +            print _("Setup will now close.") +            raw_input() +            return False + +        raw_input(_("System check finished, hit enter to see your status report.")) +        print "" +        print _("## Status ##") + +        print _("py-crypto available") if self.check_module("Crypto") else _("no py-crypto available") +        print _("You need this if you want to decrypt container files.") +        print "" +        print _("SSL available") if ssl else _("no SSL available") +        print _("This is needed if you want to establish a secure connection to core or webinterface.") +        print _("If you only want to access locally to pyLoad ssl is not usefull.") +        print "" +        print _("Captcha Recognition available") if captcha else _("no Captcha Recognition available") +        print _("Only needed for some hosters and as freeuser.") +        print "" +        print _("Gui available") if gui else _("Gui not available") +        print _("The Graphical User Interface.") +        print "" +        print _("Webinterface available") if web else _("no Webinterface available") +        print _("Gives abillity to control pyLoad with your webbrowser.") +        print "" +        print _("You can abort the setup now and fix some dependicies if you want.") + +        con = self.ask(_("Continue with setup?"), "y", bool=True) + +        if not con: +            return False + +        print "" +        print _("Do you want to configure basic settings?") +        print _("This is recommend for first run.") +        con = self.ask(_("Make basic setup?"), "y", bool=True) + +        if con: +            self.conf_basic() + +        if ssl: +            print "" +            print _("Do you want to configure ssl?") +            ssl = self.ask(_("Configure ssl?"), "n", bool=True) +            if ssl: +                self.conf_ssl() + +        if web: +            print "" +            print _("Do you want to configure webinterface?") +            web = self.ask(_("Configure webinterface?"), "y", bool=True) +            if web: +                self.conf_web() + +        print "" +        print _("Setup finished successfully.") +        return True + +    def system_check(self): +        """ make a systemcheck and return the results""" +        print _("## System Check ##") + +        python = False + +        if sys.version_info > (2, 7): +            print _("Your python version is to new, Please use Python 2.6") +            python = False +        elif sys.version_info < (2, 5): +            print _("Your python version is to old, Please use at least Python 2.5") +            python = False +        else: +            print _("Python Version: OK") +            python = True + +        if not self.check_prog(["python", "-V"]): +            print _("Unable to execute the 'python' command") +            print _("Please add python to system path or create a symlink") +            python = False + +        curl = self.check_module("pycurl") +        self.print_dep("pycurl", curl) + +        crypto = self.check_module("Crypto") +        self.print_dep("pycrypto", crypto) + +        basic = python and curl + +        ssl = self.check_module("OpenSSL") +        self.print_dep("OpenSSL", ssl) + +        print "" + +        pil = self.check_module("Image") +        self.print_dep("py-imaging", pil) + +        tesser = self.check_prog(["tesseract", "-v"]) +        self.print_dep("tesseract", tesser) + +        gocr = self.check_prog(["gocr", "-h"]) +        self.print_dep("gocr", gocr) + +        captcha = pil and tesser + +        print "" + +        gui = self.check_module("PyQt4") +        self.print_dep("PyQt4", gui) + +        print "" + +        web = self.check_module("django") +        sqlite = self.check_module("sqlite3") + +        try: +            import django + +            if django.VERSION < (1, 1): +                print _("Your django version is to old, please upgrade to django 1.1") +                web = False +            elif django.VERSION > (1, 3): +                print _("Your django version is to new, please use django 1.2") +                web = False +        except: +            web = False + +        self.print_dep("django", web) +        self.print_dep("sqlite3", sqlite) +        web = web and sqlite + +        return (basic, ssl, captcha, gui, web) + +    def conf_basic(self): +        print "" +        print _("## Basic Setup ##") + +        print "" +        print _("The following logindata are only valid for CLI and GUI, but NOT for webinterface.") +        self.config["general"]["username"] = self.ask(_("Username"), "User") +        self.config["general"]["password"] = self.ask("", "", password=True) + +        print "" +        self.config["general"]["language"] = self.ask(_("Language"), "en", ["en", "de", "fr", "nl", "pl"]) +        self.config["general"]["download_Folder"] = self.ask(_("Downloadfolder"), "Downloads") +        self.config["general"]["max_downloads"] = self.ask(_("Max parallel downloads"), "3") +        print _("You should disable checksum proofing, if you have low hardware requirements.") +        self.config["general"]["checksum"] = self.ask(_("Proof checksum?"), "y", bool=True) + +        reconnect = self.ask(_("Use Reconnect?"), "n", bool=True) +        self.config["reconnect"]["activated"] = reconnect +        if reconnect: +            self.config["reconnect"]["method"] = self.ask(_("Reconnect script location"), "./reconnect.sh") + + +    def conf_web(self): +        print "" +        print _("## Webinterface Setup ##") + +        db_path = join(self.path, "module", "web", "pyload.db") +        is_db = isfile(db_path) +        db_setup = True + +        if is_db: +            print _("You already have a database for the webinterface.") +            db_setup = self.ask(_("Do you want to delete it and make a new one?"), "n", bool=True) + +        if db_setup: +            if is_db: remove(db_path) +            import sqlite3 + +             +            print "" +            call(["python", join(self.path, "module", "web", "manage.py"), "syncdb", "--noinput"]) +            print _("If you see no errors, your db should be fine and we're adding an user now.") +            username = self.ask(_("Username"), "User") +            call(['python', join(self.path, "module", "web", "manage.py"), 'createsuperuser', '--email=email@trash-mail.com', '--username=%s' % username, '--noinput']) + +            password = self.ask("", "", password=True) +            salt = reduce(lambda x, y: x + y, [str(random.randint(0, 9)) for i in range(0, 5)]) +            hash = sha1(salt + password) +            password = "sha1$%s$%s" % (salt, hash.hexdigest()) + +            conn = sqlite3.connect(db_path) +            c = conn.cursor() +            c.execute('UPDATE "main"."auth_user" SET "password"=? WHERE "username"=?', (password, username)) + +            conn.commit() +            c.close() + +        print "" +        self.config["webinterface"]["activated"] = self.ask(_("Activate webinterface?"), "y", bool=True) +        print "" +        print _("Listen address, if you use 127.0.0.1 or localhost, the webinterface will only accessible locally.") +        self.config["webinterface"]["host"] = self.ask(_("Address"), "0.0.0.0") +        self.config["webinterface"]["port"] = self.ask(_("Port"), "8000") +        #@TODO setup for additional webservers + +    def conf_ssl(self): +        print "" +        print _("## SSL Setup ##") +        print "" +        print _("Execute these commands from pyLoad folder to make ssl certificates:") +        print "" +        print "openssl genrsa - 1024 > ssl.key" +        print "openssl req -new -key ssl.key -out ssl.csr" +        print "openssl req -days 36500 -x509 -key ssl.key -in ssl.csr > ssl.crt " +        print "" +        print _("If you're done and everything went fine, you can activate ssl now.") + +        self.config["ssl"]["activated"] = self.ask(_("Activate SSL?"), "y", bool=True) + +    def set_user(self): + +        translation = gettext.translation("setup", join(self.path, "locale"), languages=[self.config["general"]["language"]]) +        translation.install(unicode=(True if  sys.getfilesystemencoding().startswith("utf") else False)) +   +        self.ask(_("Username"), "User") +        self.ask("", "", password=True) + +    def print_dep(self, name, value): +        """Print Status of dependency""" +        if value: +            print _("%s: OK" % name) +        else: +            print _("%s: missing" % name) + + +    def check_module(self, module): +        try: +            __import__(module) +            return True +        except: +            return False + +    def check_prog(self, command): +        pipe = PIPE +        try: +            call(command, stdout=pipe, stderr=pipe) +            return True +        except: +            return False + +    def ask(self, qst, default, answers=[], bool=False, password=False): +        """produce one line to asking for input""" +        if answers: +            info = "(" + +            for i, answer in enumerate(answers): +                info += (", " if i != 0 else "") + str((answer == default and "[%s]" % answer) or answer) + +            info += ")" +        elif bool: +            if default == "y": +                info = "([y]/n)" +            else: +                info = "(y/[n])" +        else: +            info = "[%s]" % default + +        if password: +            p1 = True +            p2 = False +            while p1 != p2: +                p1 = getpass(_("Password: ")) + +                if len(p1) < 4: +                    print _("Password to short. Use at least 4 symbols.") +                    continue + +                p2 = getpass(_("Password (again): ")) + +                if p1 == p2: +                    return p1 +                else: +                    print _("Passwords did not match.") + +        while True: +            input = raw_input(qst + " %s: " % info) + +            if input.strip() == "": +                input = default + +            if bool: +                if re.match(r"(y|yes|j|ja|true)", input.lower().strip()): +                    return True +                elif re.match(r"(n|no|nein|false)", input.lower().strip()): +                    return False +                else: +                    print _("Invalid Input") +                    continue + + +            if not answers: +                return input + +            else: +                if input in answers: +                    return input +                else: +                    print _("Invalid Input") + + +if __name__ == "__main__": +    test = Setup(join(abspath(dirname(__file__)), ".."), None) +    test.start() diff --git a/module/web/ServerThread.py b/module/web/ServerThread.py index 0fbb65dfa..718dd6136 100644 --- a/module/web/ServerThread.py +++ b/module/web/ServerThread.py @@ -6,7 +6,7 @@ from subprocess import PIPE  from subprocess import Popen  from subprocess import call  from sys import version_info -from sys import stdout +from cStringIO import StringIO  import threading  class WebServer(threading.Thread): @@ -23,10 +23,11 @@ class WebServer(threading.Thread):          host = self.pycore.config['webinterface']['host']          port = self.pycore.config['webinterface']['port']          path = join(self.pycore.path, "module", "web") +        out = StringIO()          if not exists(join(self.pycore.path, "module", "web", "pyload.db")):              print "########## IMPORTANT ###########" -            print "###        Database for Webinterface doesnt exitst, it will not be available." +            print "###        Database for Webinterface does not exitst, it will not be available."              print "###        Please run: python %s syncdb" % join(self.pycore.path, "module", "web", "manage.py")              print "###        You have to add at least one User, to gain access to webinterface: python %s createsuperuser" % join(self.pycore.path, "module", "web", "manage.py")              print "###        Dont forget to restart pyLoad if you are done." @@ -107,10 +108,10 @@ class WebServer(threading.Thread):              new_config.close()              command = ['python', join(self.pycore.path, "module", "web", "manage.py"), "runfcgi", "daemonize=false", "method=threaded", "host=127.0.0.1", "port=9295"] -            self.p = Popen(command, stderr=PIPE, stdin=PIPE, stdout=Output(stdout)) +            self.p = Popen(command, stderr=Output(out), stdin=PIPE, stdout=Output(out))              command2 = ['nginx', '-c', join(path, "servers", "nginx.conf"),] -            self.p2 = Popen(command2, stderr=PIPE, stdin=PIPE, stdout=Output(stdout)) +            self.p2 = Popen(command2, stderr=PIPE, stdin=PIPE, stdout=Output(out))          elif self.server == "lighttpd": @@ -139,21 +140,21 @@ class WebServer(threading.Thread):              new_config.close()              command = ['python', join(self.pycore.path, "module", "web", "manage.py"), "runfcgi", "daemonize=false", "method=threaded", "host=127.0.0.1", "port=9295"] -            self.p = Popen(command, stderr=PIPE, stdin=PIPE, stdout=Output(stdout)) +            self.p = Popen(command, stderr=Output(out), stdin=PIPE, stdout=Output(out))              command2 = ['lighttpd', '-D', '-f', join(path, "servers", "lighttpd.conf")] -            self.p2 = Popen(command2, stderr=PIPE, stdin=PIPE, stdout=Output(stdout)) +            self.p2 = Popen(command2, stderr=PIPE, stdin=PIPE, stdout=Output(out))          elif self.server == "builtin":              self.pycore.logger.info("Starting django builtin Webserver: %s:%s" % (host, port))              command = ['python', join(self.pycore.path, "module", "web", "run_server.py"), "%s:%s" % (host, port)] -            self.p = Popen(command, stderr=Output(stdout), stdin=PIPE, stdout=Output(stdout)) +            self.p = Popen(command, stderr=Output(out), stdin=Output(out), stdout=Output(out))          else:              #run fastcgi on port              command = ['python', join(self.pycore.path, "module", "web", "manage.py"), "runfcgi", "daemonize=false", "method=threaded", "host=127.0.0.1", "port=%s" % port] -            self.p = Popen(command, stderr=PIPE, stdin=PIPE, stdout=Output(stdout)) +            self.p = Popen(command, stderr=Output(out), stdin=PIPE, stdout=Output(out))      def quit(self): @@ -173,11 +174,15 @@ class WebServer(threading.Thread):          self.running = False  class Output: -     def __init__(self, stream): +    def __init__(self, stream):          self.stream = stream -     def write(self, data): # Do nothing + +    def fileno(self): +        return 1 + +    def write(self, data): # Do nothing          return None           #self.stream.write(data)           #self.stream.flush() -     def __getattr__(self, attr): +    def __getattr__(self, attr):          return getattr(self.stream, attr)
\ No newline at end of file | 
