def add_plugin(self, plugin, activate=False): plugin_class = plugin.load_module() if plugin_class is None: return None if plugin in self.plugins: log.info('Not loading plugin %s v %s. Plugin already loaded.', plugin.short_name, plugin.version) return None try: plugin_obj = plugin_class() except Exception: log.exception('Error while loading a plugin') return None if plugin.short_name not in app.settings.get_plugins(): app.settings.set_plugin_setting(plugin.short_name, 'active', plugin.shipped) self.plugins.append(plugin_obj) plugin_obj.active = False if activate: self.activate_plugin(plugin_obj) app.nec.push_incoming_event( NetworkEvent('plugin-added', plugin=plugin_obj)) return plugin_obj
def add_plugin(self, plugin_class): ''' :todo: what about adding plug-ins that are already added? Module reload and adding class from reloaded module or ignoring adding plug-in? ''' try: plugin = plugin_class() except Exception: log.exception('Error while loading a plugin') return if plugin not in self.plugins: if not self._plugin_has_entry_in_global_config(plugin): self._create_plugin_entry_in_global_config(plugin) self.plugins.append(plugin) plugin.active = False app.nec.push_incoming_event( NetworkEvent('plugin-added', plugin=plugin)) else: log.info( 'Not loading plugin %s v%s from module %s ' '(identified by short name: %s). Plugin already loaded.', plugin.name, plugin.version, plugin.__module__, plugin.short_name)
def try_run(argv, directory): try: p = popen_nt_friendly(argv, directory) out = p.communicate()[0] log.info(out) return p.wait() except Exception as e: return _('Error executing "%(command)s": %(error)s') % { 'command': " ".join(argv), 'error': str(e) }
def _nec_subscribe_presence_received(self, obj): if self.config['block_subscription_requests'] and \ not app.contacts.get_contacts(obj.conn.name, obj.jid): log.info('discarding subscription request from %s', obj.jid) return True if obj.jid.split("@", 1)[1] in self.block_domains: log.info( 'discarding subscription request from %s, domain is blocked', obj.jid) return True
def _nec_message_received_received(self, obj): if self.config['disable_xhtml_muc'] and obj.mtype == 'groupchat': self.remove_xhtml(obj) if self.config['disable_xhtml_pm'] and obj.gc_control and \ obj.resource and obj.mtype == 'chat': self.remove_xhtml(obj) if obj.jid.split("@", 1)[1] in self.block_domains: log.info('discarding message from %s, domain is blocked', obj.jid) return True return False
def _nec_decrypted_message_received_received(self, obj): if not obj.msgtxt: return False if obj.jid.split("@", 1)[1] in self.block_domains: log.info('discarding message from %s, domain is blocked', obj.jid) return True if self._nec_decrypted_message_received_question(obj): return True limit = self.config['msgtxt_limit'] if limit > -1 and len(obj.msgtxt) > limit: return True return False
def add_plugin(self, plugin_class): ''' :todo: what about adding plug-ins that are already added? Module reload and adding class from reloaded module or ignoring adding plug-in? ''' plugin = plugin_class() if plugin not in self.plugins: if not self._plugin_has_entry_in_global_config(plugin): self._create_plugin_entry_in_global_config(plugin) self.plugins.append(plugin) plugin.active = False else: log.info('Not loading plugin %s v%s from module %s (identified by' ' short name: %s). Plugin already loaded.' % (plugin.name, plugin.version, plugin.__module__, plugin.short_name))
def send_question(self, obj, jid): if obj.mtype != 'chat' and obj.mtype != 'normal': log.info('Anti_spam wrong message type: %s', obj.mtype) return question = self.config['msgtxt_question'] log.info('Anti_spam enabled for %s, question: %s', jid, question) message = _('Antispam enabled. Please answer the question. The message must only ' + \ 'contain the answer. (Messages sent before the correct answer, will be lost): ') \ + question if obj.mtype == 'chat': stanza = nbxmpp.Message(to=jid, body=message, typ=obj.mtype) else: # for 'normal' type stanza = nbxmpp.Message(to=jid, body=message, subject='Antispam enabled', typ=obj.mtype) app.connections[obj.conn.name].connection.send(stanza)
def _load_plugins(self): plugins = {} for plugin_dir in configpaths.get_plugin_dirs(): if not plugin_dir.is_dir(): continue for plugin_path in plugin_dir.iterdir(): plugin = self._load_plugin(plugin_path) if plugin is None: continue same_plugin = plugins.get(plugin.short_name) if same_plugin is not None: if same_plugin.version > plugin.version: continue log.info('Found plugin %s %s', plugin.short_name, plugin.version) plugins[plugin.short_name] = plugin for plugin in plugins.values(): self.add_plugin(plugin)
def scan_dir_for_plugins(path, scan_dirs=True, package=False): r''' Scans given directory for plugin classes. :param path: directory to scan for plugins :type path: str :param scan_dirs: folders inside path are processed as modules :type scan_dirs: boolean :param package: if path points to a single package folder :type package: boolean :return: list of found plugin classes (subclasses of `GajimPlugin` :rtype: [] of class objects :note: currently it only searches for plugin classes in '\*.py' files present in given directory `path` (no recursion here) :todo: add scanning zipped modules ''' from gajim.plugins.plugins_i18n import _ plugins_found = [] conf = configparser.ConfigParser() fields = ('name', 'short_name', 'version', 'description', 'authors', 'homepage') if not os.path.isdir(path): return plugins_found if package: path, package_name = os.path.split(path) dir_list = [package_name] else: dir_list = os.listdir(path) sys.path.insert(0, path) for elem_name in dir_list: file_path = os.path.join(path, elem_name) if os.path.isfile(file_path) and fnmatch.fnmatch( file_path, '*.py'): module_name = os.path.splitext(elem_name)[0] elif os.path.isdir(file_path) and scan_dirs: module_name = elem_name file_path += os.path.sep else: continue manifest_path = os.path.join(os.path.dirname(file_path), 'manifest.ini') if scan_dirs and (not os.path.isfile(manifest_path)): continue # read metadata from manifest.ini conf.remove_section('info') with open(manifest_path, encoding='utf-8') as conf_file: try: conf.read_file(conf_file) except configparser.Error: log.warning(("Plugin {plugin} not loaded, error loading" " manifest").format(plugin=elem_name), exc_info=True) continue min_v = conf.get('info', 'min_gajim_version', fallback=None) max_v = conf.get('info', 'max_gajim_version', fallback=None) gajim_v = gajim.__version__.split('+', 1)[0] gajim_v_cmp = parse_version(gajim_v) if min_v and gajim_v_cmp < parse_version(min_v): log.warning(('Plugin {plugin} not loaded, newer version of' 'gajim required: {gajim_v} < {min_v}').format( plugin=elem_name, gajim_v=gajim_v, min_v=min_v)) continue if max_v and gajim_v_cmp > parse_version(max_v): log.warning(('Plugin {plugin} not loaded, plugin incompatible ' 'with current version of gajim: ' '{gajim_v} > {max_v}').format(plugin=elem_name, gajim_v=gajim_v, max_v=max_v)) continue module = None try: log.info('Loading %s', module_name) module = __import__(module_name) except Exception as error: log.warning( "While trying to load {plugin}, exception occurred".format( plugin=elem_name), exc_info=sys.exc_info()) continue if module is None: continue log.debug('Attributes processing started') for module_attr_name in [ attr_name for attr_name in dir(module) if not ( attr_name.startswith('__') or attr_name.endswith('__')) ]: module_attr = getattr(module, module_attr_name) log.debug('%s : %s' % (module_attr_name, module_attr)) try: if not issubclass(module_attr, GajimPlugin) or \ module_attr is GajimPlugin: continue log.debug('is subclass of GajimPlugin') module_attr.__path__ = os.path.abspath( os.path.dirname(file_path)) for option in fields: if conf.get('info', option) is '': raise configparser.NoOptionError(option, 'info') if option == 'description': setattr(module_attr, option, _(conf.get('info', option))) continue setattr(module_attr, option, conf.get('info', option)) plugins_found.append(module_attr) except TypeError: # set plugin localization try: module_attr._ = _ except AttributeError: pass except configparser.NoOptionError: # all fields are required log.debug( '%s : %s' % (module_attr_name, 'wrong manifest file. all fields are required!')) except configparser.NoSectionError: # info section are required log.debug( '%s : %s' % (module_attr_name, 'wrong manifest file. info section are required!')) except configparser.MissingSectionHeaderError: # info section are required log.debug('%s : %s' % (module_attr_name, 'wrong manifest file. section are required!')) sys.path.remove(path) return plugins_found
def _nec_atom_entry_received(self, obj): if self.config['block_pubsub_messages']: log.info('discarding pubdubd message') return True