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]))
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)
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)
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)
def get_folder(self, name=None, absolute=True): return onionrplugins.get_plugins_folder(name=name, absolute=absolute)
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
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