Пример #1
0
def create_plugin(o_inst):
    '''
        Creates the directory structure for a plugin name
    '''

    if len(sys.argv) >= 3:
        try:
            plugin_name = re.sub('[^0-9a-zA-Z_]+', '', str(sys.argv[2]).lower())

            if not plugins.exists(plugin_name):
                logger.info('Creating plugin "%s"...' % plugin_name)

                os.makedirs(plugins.get_plugins_folder(plugin_name))
                with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main:
                    contents = ''
                    with open('static-data/default_plugin.py', 'rb') as file:
                        contents = file.read().decode()

                    # TODO: Fix $user. os.getlogin() is   B U G G Y
                    main.write(contents.replace('$user', 'some random developer').replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')).replace('$name', plugin_name))

                with open(plugins.get_plugins_folder(plugin_name) + '/info.json', 'a') as main:
                    main.write(json.dumps({'author' : 'anonymous', 'description' : 'the default description of the plugin', 'version' : '1.0'}))

                logger.info('Enabling plugin "%s"...' % plugin_name)
                plugins.enable(plugin_name, o_inst)
            else:
                logger.warn('Cannot create plugin directory structure; plugin "%s" exists.' % plugin_name)

        except Exception as e:
            logger.error('Failed to create plugin directory structure.', e)
    else:
        logger.info('%s %s <plugin>' % (sys.argv[0], sys.argv[1]))
Пример #2
0
    def testPluginEvent(self):
        logger.debug('-' * 26 + '\n')
        logger.info('Running plugin event test...')

        import onionrplugins as plugins, onionrevents as events, os

        if not plugins.exists('test'):
            os.makedirs(plugins.get_plugins_folder('test'))
            with open(plugins.get_plugins_folder('test') + '/main.py',
                      'a') as main:
                main.write(
                    "print('Running')\n\ndef on_test(pluginapi, data = None):\n    print('received test event!')\n    print('thread test started...')\n    import time\n    time.sleep(1)\n    \n    return True\n\ndef on_start(pluginapi, data = None):\n    print('start event called')\n\ndef on_stop(pluginapi, data = None):\n    print('stop event called')\n\ndef on_enable(pluginapi, data = None):\n    print('enable event called')\n\ndef on_disable(pluginapi, data = None):\n    print('disable event called')\n"
                )
            plugins.enable('test')

        plugins.start('test')
        if not events.call(plugins.get_plugin('test'), 'enable'):
            self.assertTrue(False)

        logger.debug('preparing to start thread', timestamp=False)
        thread = events.event('test', data={'tests': self})
        logger.debug('thread running...', timestamp=False)
        thread.join()
        logger.debug('thread finished.', timestamp=False)

        self.assertTrue(True)
Пример #3
0
def setup_default_plugins():
    # Copy default plugins into plugins folder
    if not os.path.exists(plugins.get_plugins_folder()):
        if os.path.exists(get_static_dir() + '/default-plugins/'):
            names = [f for f in os.listdir(get_static_dir() + '/default-plugins/')]
            try:
                shutil.copytree(
                    get_static_dir() + '/default-plugins/',
                    plugins.get_plugins_folder())
            except FileExistsError:
                pass

            # Enable plugins
            for name in names:
                if not name in plugins.get_enabled_plugins():
                    plugins.enable(name)

    for name in plugins.get_enabled_plugins():
        if not os.path.exists(plugins.get_plugin_data_folder(name)):
            try:
                os.mkdir(plugins.get_plugin_data_folder(name))
            except FileExistsError:
                pass
            except Exception as e:
                #logger.warn('Error enabling plugin: ' + str(e), terminal=True)
                plugins.disable(name, stop_event = False)
Пример #4
0
    def testPluginReload(self):
        logger.debug('-' * 26 + '\n')
        logger.info('Running simple plugin reload test...')

        import onionrplugins, os

        if not onionrplugins.exists('test'):
            os.makedirs(onionrplugins.get_plugins_folder('test'))
            with open(
                    onionrplugins.get_plugins_folder('test') + '/main.py',
                    'a') as main:
                main.write(
                    "print('Running')\n\ndef on_test(pluginapi, data = None):\n    print('received test event!')\n    return True\n\ndef on_start(pluginapi, data = None):\n    print('start event called')\n\ndef on_stop(pluginapi, data = None):\n    print('stop event called')\n\ndef on_enable(pluginapi, data = None):\n    print('enable event called')\n\ndef on_disable(pluginapi, data = None):\n    print('disable event called')\n"
                )
            onionrplugins.enable('test')

        try:
            onionrplugins.reload('test')
            self.assertTrue(True)
        except:
            self.assertTrue(False)
Пример #5
0
 def get_folder(self, name=None, absolute=True):
     return onionrplugins.get_plugins_folder(name=name, absolute=absolute)
Пример #6
0
    def __init__(self):
        '''
            Main Onionr class. This is for the CLI program, and does not handle much of the logic.
            In general, external programs and plugins should not use this class.
        '''

        try:
            os.chdir(sys.path[0])
        except FileNotFoundError:
            pass

        # Load global configuration data

        data_exists = os.path.exists('data/')

        if not data_exists:
            os.mkdir('data/')

        if os.path.exists('static-data/default_config.json'):
            config.set_config(
                json.loads(open('static-data/default_config.json').read())
            )  # this is the default config, it will be overwritten if a config file already exists. Else, it saves it
        else:
            # the default config file doesn't exist, try hardcoded config
            config.set_config({
                'devmode': True,
                'log': {
                    'file': {
                        'output': True,
                        'path': 'data/output.log'
                    },
                    'console': {
                        'output': True,
                        'color': True
                    }
                }
            })
        if not data_exists:
            config.save()
        config.reload()  # this will read the configuration file into memory

        settings = 0b000
        if config.get('log', {'console': {'color': True}})['console']['color']:
            settings = settings | logger.USE_ANSI
        if config.get('log', {'console': {
                'output': True
        }})['console']['output']:
            settings = settings | logger.OUTPUT_TO_CONSOLE
        if config.get('log', {'file': {'output': True}})['file']['output']:
            settings = settings | logger.OUTPUT_TO_FILE
            logger.set_file(
                config.get('log', {'file': {
                    'path': 'data/output.log'
                }})['file']['path'])
        logger.set_settings(settings)

        if str(config.get('devmode', True)).lower() == 'true':
            self._developmentMode = True
            logger.set_level(logger.LEVEL_DEBUG)
        else:
            self._developmentMode = False
            logger.set_level(logger.LEVEL_INFO)

        self.onionrCore = core.Core()
        self.onionrUtils = OnionrUtils(self.onionrCore)

        # Handle commands

        self.debug = False  # Whole application debugging

        if os.path.exists('data-encrypted.dat'):
            while True:
                print('Enter password to decrypt:')
                password = getpass.getpass()
                result = self.onionrCore.dataDirDecrypt(password)
                if os.path.exists('data/'):
                    break
                else:
                    logger.error('Failed to decrypt: ' + result[1],
                                 timestamp=False)
        else:
            # If data folder does not exist
            if not data_exists:
                if not os.path.exists('data/blocks/'):
                    os.mkdir('data/blocks/')

            # Copy default plugins into plugins folder
            if not os.path.exists(plugins.get_plugins_folder()):
                if os.path.exists('static-data/default-plugins/'):
                    names = [
                        f for f in os.listdir("static-data/default-plugins/")
                        if not os.path.isfile(f)
                    ]
                    shutil.copytree('static-data/default-plugins/',
                                    plugins.get_plugins_folder())

                    # Enable plugins
                    for name in names:
                        if not name in plugins.get_enabled_plugins():
                            plugins.enable(name, self)

        for name in plugins.get_enabled_plugins():
            if not os.path.exists(plugins.get_plugin_data_folder(name)):
                try:
                    os.mkdir(plugins.get_plugin_data_folder(name))
                except:
                    plugins.disable(name, onionr=self, stop_event=False)

        if not os.path.exists(self.onionrCore.peerDB):
            self.onionrCore.createPeerDB()
            pass
        if not os.path.exists(self.onionrCore.addressDB):
            self.onionrCore.createAddressDB()

        # Get configuration

        if not data_exists:
            # Generate default config
            # Hostname should only be set if different from 127.x.x.x. Important for DNS rebinding attack prevention.
            if self.debug:
                randomPort = 8080
            else:
                while True:
                    randomPort = random.randint(1024, 65535)
                    if self.onionrUtils.checkPort(randomPort):
                        break
            config.set(
                'client', {
                    'participate': 'true',
                    'client_hmac': base64.b16encode(
                        os.urandom(32)).decode('utf-8'),
                    'port': randomPort,
                    'api_version': API_VERSION
                }, True)

        self.cmds = {
            '': self.showHelpSuggestion,
            'help': self.showHelp,
            'version': self.version,
            'config': self.configure,
            'start': self.start,
            'stop': self.killDaemon,
            'status': self.showStats,
            'statistics': self.showStats,
            'stats': self.showStats,
            'enable-plugin': self.enablePlugin,
            'enplugin': self.enablePlugin,
            'enableplugin': self.enablePlugin,
            'enmod': self.enablePlugin,
            'disable-plugin': self.disablePlugin,
            'displugin': self.disablePlugin,
            'disableplugin': self.disablePlugin,
            'dismod': self.disablePlugin,
            'reload-plugin': self.reloadPlugin,
            'reloadplugin': self.reloadPlugin,
            'reload-plugins': self.reloadPlugin,
            'reloadplugins': self.reloadPlugin,
            'create-plugin': self.createPlugin,
            'createplugin': self.createPlugin,
            'plugin-create': self.createPlugin,
            'listkeys': self.listKeys,
            'list-keys': self.listKeys,
            'addmsg': self.addMessage,
            'addmessage': self.addMessage,
            'add-msg': self.addMessage,
            'add-message': self.addMessage,
            'pm': self.sendEncrypt,
            'getpms': self.getPMs,
            'get-pms': self.getPMs,
            'addpeer': self.addPeer,
            'add-peer': self.addPeer,
            'add-address': self.addAddress,
            'add-addr': self.addAddress,
            'addaddr': self.addAddress,
            'addaddress': self.addAddress,
            'addfile': self.addFile,
            'importblocks': self.onionrUtils.importNewBlocks,
            'introduce': self.onionrCore.introduceNode,
            'connect': self.addAddress
        }

        self.cmdhelp = {
            'help': 'Displays this Onionr help menu',
            'version': 'Displays the Onionr version',
            'config': 'Configures something and adds it to the file',
            'start': 'Starts the Onionr daemon',
            'stop': 'Stops the Onionr daemon',
            'stats': 'Displays node statistics',
            'enable-plugin': 'Enables and starts a plugin',
            'disable-plugin': 'Disables and stops a plugin',
            'reload-plugin': 'Reloads a plugin',
            'create-plugin': 'Creates directory structure for a plugin',
            'add-peer': 'Adds a peer to database',
            'list-peers': 'Displays a list of peers',
            'add-msg': 'Broadcasts a message to the Onionr network',
            'pm': 'Adds a private message to block',
            'get-pms': 'Shows private messages sent to you',
            'addfile': 'Create an Onionr block from a file',
            'importblocks':
            'import blocks from the disk (Onionr is transport-agnostic!)',
            'introduce': 'Introduce your node to the public Onionr network',
        }

        # initialize plugins
        events.event('init', onionr=self, threaded=False)

        command = ''
        try:
            command = sys.argv[1].lower()
        except IndexError:
            command = ''
        finally:
            self.execute(command)

        if not self._developmentMode:
            encryptionPassword = self.onionrUtils.getPassword(
                'Enter password to encrypt directory: ')
            self.onionrCore.dataDirEncrypt(encryptionPassword)
            shutil.rmtree('data/')

        return
Пример #7
0
    def __init__(self):
        '''
            Main Onionr class. This is for the CLI program, and does not handle much of the logic.
            In general, external programs and plugins should not use this class.
        '''
        self.userRunDir = os.getcwd() # Directory user runs the program from
        self.killed = False

        if sys.argv[0] == os.path.basename(__file__):
            try:
                os.chdir(sys.path[0])
            except FileNotFoundError:
                pass

        # set data dir
        self.dataDir = os.environ.get('ONIONR_HOME', os.environ.get('DATA_DIR', 'data/'))
        if not self.dataDir.endswith('/'):
            self.dataDir += '/'

        # set log file
        logger.set_file(os.environ.get('LOG_DIR', 'data') + '/onionr.log')

        # Load global configuration data
        data_exists = Onionr.setupConfig(self.dataDir, self)

        if netcontroller.torBinary() is None:
            logger.error('Tor is not installed')
            sys.exit(1)

        # If block data folder does not exist
        if not os.path.exists(self.dataDir + 'blocks/'):
            os.mkdir(self.dataDir + 'blocks/')

        # Copy default plugins into plugins folder
        if not os.path.exists(plugins.get_plugins_folder()):
            if os.path.exists('static-data/default-plugins/'):
                names = [f for f in os.listdir("static-data/default-plugins/")]
                shutil.copytree('static-data/default-plugins/', plugins.get_plugins_folder())

                # Enable plugins
                for name in names:
                    if not name in plugins.get_enabled_plugins():
                        plugins.enable(name, self)

        for name in plugins.get_enabled_plugins():
            if not os.path.exists(plugins.get_plugin_data_folder(name)):
                try:
                    os.mkdir(plugins.get_plugin_data_folder(name))
                except:
                    plugins.disable(name, onionr = self, stop_event = False)

        self.communicatorInst = None
        self.onionrCore = core.Core()
        self.onionrCore.onionrInst = self
        #self.deleteRunFiles()
        self.onionrUtils = onionrutils.OnionrUtils(self.onionrCore)

        self.clientAPIInst = '' # Client http api instance
        self.publicAPIInst = '' # Public http api instance

        signal.signal(signal.SIGTERM, self.exitSigterm)

        # Handle commands

        self.debug = False # Whole application debugging

        # Get configuration
        if type(config.get('client.webpassword')) is type(None):
            config.set('client.webpassword', base64.b16encode(os.urandom(32)).decode('utf-8'), savefile=True)
        if type(config.get('client.client.port')) is type(None):
            randomPort = netcontroller.getOpenPort()
            config.set('client.client.port', randomPort, savefile=True)
        if type(config.get('client.public.port')) is type(None):
            randomPort = netcontroller.getOpenPort()
            config.set('client.public.port', randomPort, savefile=True)
        if type(config.get('client.api_version')) is type(None):
            config.set('client.api_version', API_VERSION, savefile=True)

        self.cmds = commands.get_commands(self)
        self.cmdhelp = commands.cmd_help

        # initialize plugins
        events.event('init', onionr = self, threaded = False)

        command = ''
        try:
            command = sys.argv[1].lower()
        except IndexError:
            command = ''
        finally:
            self.execute(command)

        return