Example #1
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()

        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(_("Start initial webinterface for configuration?"), self.yes, bool=True)
        if viaweb:
            self.start_web()
        else:
            self.start_cli()
Example #2
0
class Core(object):
    """pyLoad Core, one tool to rule them all... (the filehosters) :D"""

    def __init__(self, **kwargs):
        if kwargs.get('display_version'):
            print("pyLoad", CURRENT_VERSION)
            exit()
        elif kwargs.get('do_clean'):
            self.cleanTree()
            exit()
        elif kwargs.get('user'):
            from module.setup import Setup

            self.config = ConfigParser()
            s = Setup(pypath, self.config)
            s.set_user()
            exit()
        elif kwargs.get('setup'):
            from module.setup import Setup

            self.config = ConfigParser()
            s = Setup(pypath, self.config)
            s.start()
            exit()
        elif kwargs.get('change_dir'):
            from module.setup import Setup

            self.config = ConfigParser()
            s = Setup(pypath, self.config)
            s.conf_path(True)
            exit()
        elif kwargs.get('do_quit'):
            self.quitInstance()
            exit()
        elif kwargs.get('display_status'):
            pid = self.isAlreadyRunning()
            if self.isAlreadyRunning():
                print(pid)
                exit(0)
            else:
                print("false")
                exit(1)

        self.running = False
        self.pidfile = kwargs.get('pidfile') or 'pyload.pid'
        self.doDebug = bool(kwargs.get('do_debug'))
        self.remote = not bool(kwargs.get('no_remote'))
        self.daemon = bool(kwargs.get('is_daemon'))
        self.deleteLinks = bool(kwargs.get('do_clear'))  # will delete links on startup

    def toggle_pause(self):
        thread_manager = get_thread_manager()

        thread_manager.pause = not thread_manager.pause
        return thread_manager.pause

    def quit(self, a, b):
        self.shutdown()
        self.log.info(_("Received Quit signal"))
        _exit(1)

    def writePidFile(self):
        self.deletePidFile()
        pid = os.getpid()
        f = open(self.pidfile, "wb")
        f.write(smart_bytes(pid))
        f.close()

    def deletePidFile(self):
        if self.checkPidFile():
            self.log.debug("Deleting old pidfile %s" % self.pidfile)
            os.remove(self.pidfile)

    def checkPidFile(self):
        """ return pid as int or 0"""
        if os.path.isfile(self.pidfile):
            f = open(self.pidfile, "rb")
            pid = f.read().strip()
            f.close()
            if pid:
                pid = int(pid)
                return pid

        return 0

    def isAlreadyRunning(self):
        pid = self.checkPidFile()
        if not pid or IS_WINDOWS:
            return False
        try:
            os.kill(pid, 0)  # 0 - default signal (does nothing)
        except Exception:
            return 0

        return pid

    def quitInstance(self):
        if IS_WINDOWS:
            print("Not supported on windows.")
            return

        pid = self.isAlreadyRunning()
        if not pid:
            print("No pyLoad running.")
            return

        try:
            os.kill(pid, 3) #SIGUIT

            t = time()
            print("waiting for pyLoad to quit")

            while exists(self.pidfile) and t + 10 > time():
                sleep(0.25)

            if not exists(self.pidfile):
                print("pyLoad successfully stopped")
            else:
                os.kill(pid, 9) #SIGKILL
                print("pyLoad did not respond")
                print("Kill signal was send to process with id %s" % pid)

        except:
            print("Error quitting pyLoad")


    def cleanTree(self):
        for path, dirs, files in walk(self.path("")):
            for f in files:
                if not f.endswith(".pyo") and not f.endswith(".pyc"):
                    continue

                if "_25" in f or "_26" in f or "_27" in f:
                    continue

                print(join(path, f))
                remove(join(path, f))

    def start(self, rpc=True, web=True):
        """ starts the fun :D """

        self.version = CURRENT_VERSION

        if not exists("pyload.conf"):
            from module.setup import Setup

            print("This is your first start, running configuration assistent now.")
            self.config = ConfigParser()
            s = Setup(pypath, self.config)
            res = False
            try:
                res = s.start()
            except SystemExit:
                pass
            except KeyboardInterrupt:
                print("\nSetup interrupted")
            except:
                res = False
                print_exc()
                print("Setup failed")
            if not res:
                remove("pyload.conf")

            exit()

        try: signal.signal(signal.SIGQUIT, self.quit)
        except: pass

        self.config = ConfigParser()

        gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None])
        translation = gettext.translation("pyLoad", self.path("locale"),
                                          languages=[self.config['general']['language'],"en"],fallback=True)
        install_translation(translation)

        self.debug = self.doDebug or self.config['general']['debug_mode']
        self.remote &= self.config['remote']['activated']

        pid = self.isAlreadyRunning()
        if pid:
            print(_("pyLoad already running with pid %s") % pid)
            exit()

        if not IS_WINDOWS and self.config["general"]["renice"]:
            os.system("renice %d %d" % (self.config["general"]["renice"], os.getpid()))

        if self.config["permission"]["change_group"]:
            if not IS_WINDOWS:
                try:
                    from grp import getgrnam

                    group = getgrnam(self.config["permission"]["group"])
                    os.setgid(group[2])
                except Exception as e:
                    print(_("Failed changing group: %s") % e)

        if self.config["permission"]["change_user"]:
            if not IS_WINDOWS:
                try:
                    from pwd import getpwnam

                    user = getpwnam(self.config["permission"]["user"])
                    os.setuid(user[2])
                except Exception as e:
                    print(_("Failed changing user: %s") % e)

        self.check_file(
            self.config['log']['log_folder'],
            _("folder for logs"),
            is_folder=True,
        )

        if self.debug:
            self.init_logger(logging.DEBUG) # logging level
        else:
            self.init_logger(logging.INFO) # logging level

        sys.excepthook = exceptHook

        self.do_kill = False
        self.do_restart = False
        self.shuttedDown = False

        self.log.info(_("Starting") + " pyLoad %s" % CURRENT_VERSION)
        self.log.info(_("Using home directory: %s") % getcwd())

        self.writePidFile()

        #@TODO refractor

        remote.activated = self.remote
        self.log.debug("Remote activated: %s" % self.remote)

        self.check_install("Crypto", _("pycrypto to decode container files"))
        #img = self.check_install("Image", _("Python Image Libary (PIL) for captcha reading"))
        #self.check_install("pycurl", _("pycurl to download any files"), True, True)
        self.check_file("tmp", _("folder for temporary files"), is_folder=True)
        #tesser = self.check_install("tesseract", _("tesseract for captcha reading"), False) if not IS_WINDOWS else True

        self.captcha = True # checks seems to fail, althoug tesseract is available

        self.check_file(
            self.config['general']['download_folder'],
            _("folder for downloads"),
            is_folder=True,
        )

        if self.config['ssl']['activated']:
            self.check_install("OpenSSL", _("OpenSSL for secure connection"))

        self.setupDB()

        if self.deleteLinks:
            self.log.info(_("All links removed"))
            self.db.purgeLinks()

        set_request_factory(RequestFactory(self))

        self.lastClientConnected = 0

        # later imported because they would trigger api import, and remote value not set correctly
        from module import Api
        from module.HookManager import HookManager
        from module.ThreadManager import ThreadManager

        if Api.activated != self.remote:
            self.log.warning("Import error: API remote status not correct.")

        self.api = Api.Api(self)

        self.scheduler = Scheduler(self)

        #hell yeah, so many important managers :D
        set_plugin_manager(PluginManager(self))
        set_pull_manager(PullManager(self))
        set_thread_manager(ThreadManager(self))
        set_account_manager(AccountManager(self))
        set_captcha_manager(CaptchaManager(self))
        # HookManager sets itself as a singleton
        HookManager(self)
        set_remote_manager(RemoteManager(self))

        thread_manager = get_thread_manager()

        self.js = JsEngine()

        self.log.info(_("Downloadtime: %s") % self.api.isTimeDownload())

        if rpc:
            get_remote_manager().startBackends()

        if web:
            self.init_webserver()

        spaceLeft = freeSpace(self.config["general"]["download_folder"])

        self.log.info(_("Free space: %s") % formatSize(spaceLeft))

        self.config.save() #save so config files gets filled

        link_file = join(pypath, "links.txt")

        if exists(link_file):
            f = open(link_file, "rb")
            if f.read().strip():
                self.api.addPackage("links.txt", [link_file], 1)
            f.close()

        link_file = "links.txt"
        if exists(link_file):
            f = open(link_file, "rb")
            if f.read().strip():
                self.api.addPackage("links.txt", [link_file], 1)
            f.close()

        #self.scheduler.addJob(0, get_account_manager().getAccountInfos)
        self.log.info(_("Activating Accounts..."))
        get_account_manager().getAccountInfos()

        thread_manager.pause = False
        self.running = True

        self.log.info(_("Activating Plugins..."))
        get_hook_manager().coreReady()

        self.log.info(_("pyLoad is up and running"))

        #test api
#        from module.common.APIExerciser import startApiExerciser
#        startApiExerciser(self, 3)

        #some memory stats
#        from guppy import hpy
#        hp=hpy()
#        import objgraph
#        objgraph.show_most_common_types(limit=20)
#        import memdebug
#        memdebug.start(8002)

        locals().clear()

        while True:
            try:
                sleep(2)
            except IOError as e:
                if e.errno != 4:  # errno.EINTR
                    raise

            if self.do_restart:
                self.log.info(_("restarting pyLoad"))
                self.restart()

            if self.do_kill:
                self.shutdown()
                self.log.info(_("pyLoad quits"))
                self.removeLogger()
                _exit(0) #@TODO thrift blocks shutdown

            thread_manager.work()
            self.scheduler.work()

    def setupDB(self):
        self.db = DatabaseBackend(self) # the backend
        self.db.setup()

        self.files = FileHandler(self)
        self.db.manager = self.files #ugly?

    def init_webserver(self):
        if self.config['webinterface']['activated']:
            self.webserver = WebServer(self)
            self.webserver.start()

    def init_logger(self, level):
        console = logging.StreamHandler(sys.stdout)
        frm = logging.Formatter("%(asctime)s %(levelname)-8s  %(message)s", "%d.%m.%Y %H:%M:%S")
        console.setFormatter(frm)
        self.log = logging.getLogger("log") # settable in config

        if self.config['log']['file_log']:
            if self.config['log']['log_rotate']:
                file_handler = logging.handlers.RotatingFileHandler(
                    join(smart_text(self.config['log']['log_folder']), u'log.txt'),
                    maxBytes=self.config['log']['log_size'] * 1024,
                    backupCount=int(self.config['log']['log_count']),
                    encoding="utf8",
                )
            else:
                file_handler = logging.FileHandler(
                    join(smart_text(self.config['log']['log_folder']), u'log.txt'),
                    encoding="utf8",
                )

            file_handler.setFormatter(frm)
            self.log.addHandler(file_handler)

        self.log.addHandler(console) #if console logging
        self.log.setLevel(level)

    def removeLogger(self):
        for h in list(self.log.handlers):
            self.log.removeHandler(h)
            h.close()

    def check_install(self, check_name, legend, python=True, essential=False):
        """check wether needed tools are installed"""
        try:
            if python:
                find_module(check_name)
            else:
                pipe = subprocess.PIPE
                subprocess.Popen(check_name, stdout=pipe, stderr=pipe)

            return True
        except:
            if essential:
                self.log.info(_("Install %s") % legend)
                exit()

            return False

    def check_file(self, check_name, description, is_folder=False):
        """Check whether needed files exist."""
        file_created = True
        file_exists = True

        check_name = smart_text(check_name)

        if not exists(check_name):
            file_exists = False

            try:
                if is_folder:
                    check_name = check_name.replace(u'/', smart_text(sep))
                    os.makedirs(check_name)
                else:
                    open(check_name, "w")
            except Exception:
                file_created = False

        if not file_exists and not file_created:
            print(_("could not create %(desc)s: %(name)s") % {"desc": description, "name": check_name})

    def isClientConnected(self):
        return (self.lastClientConnected + 30) > time()

    def restart(self):
        self.shutdown()
        chdir(owd)
        # close some open fds
        for i in range(3,50):
            try:
                close(i)
            except:
                pass

        execl(executable, executable, *sys.argv)
        _exit(0)

    def shutdown(self):
        self.log.info(_("shutting down..."))
        try:
            if self.config['webinterface']['activated'] and hasattr(self, "webserver"):
                self.webserver.quit()

            for thread in get_thread_manager().threads:
                thread.put("quit")
            pyfiles = self.files.cache.values()

            for pyfile in pyfiles:
                pyfile.abortDownload()

            get_hook_manager().coreExiting()

        except:
            if self.debug:
                print_exc()
            self.log.info(_("error while shutting down"))

        finally:
            self.files.syncSave()
            self.shuttedDown = True

        self.deletePidFile()


    def path(self, *args):
        return join(pypath, *args)