def _render_view(self, req): plugins = get_plugin_info(self.env, include_core=True) def safe_wiki_to_html(context, text): try: return format_to_html(self.env, context, text) except Exception as e: self.log.error("Unable to render component documentation: %s", exception_to_unicode(e, traceback=True)) return tag.pre(text) data = { 'plugins': plugins, 'show': req.args.get('show'), 'readonly': not os.access(get_plugins_dir(self.env), os.F_OK + os.W_OK), 'safe_wiki_to_html': safe_wiki_to_html, } return 'admin_plugins.html', data
'The following components have been disabled:', len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext('The following component has been enabled:', 'The following components have been enabled:', len(added)) notices.append(tag(msg, make_list(added))) _save_config(self.config, req, self.log, notices) def _render_view(self, req): plugins = get_plugin_info(self.env, include_core=True) def safe_wiki_to_html(context, text): try: return format_to_html(self.env, context, text) except Exception, e: self.log.error('Unable to render component documentation: %s', exception_to_unicode(e, traceback=True)) return tag.pre(text) data = { 'plugins': plugins, 'show': req.args.get('show'), 'readonly': not os.access(get_plugins_dir(self.env), os.F_OK + os.W_OK), 'safe_wiki_to_html': safe_wiki_to_html, } return 'admin_plugins.html', data
msg = ngettext('The following component has been disabled:', 'The following components have been disabled:', len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext('The following component has been enabled:', 'The following components have been enabled:', len(added)) notices.append(tag(msg, make_list(added))) _save_config(self.config, req, self.log, notices) def _render_view(self, req): plugins = get_plugin_info(self.env, include_core=True) def safe_wiki_to_html(context, text): try: return format_to_html(self.env, context, text) except Exception, e: self.log.error('Unable to render component documentation: %s', exception_to_unicode(e, traceback=True)) return tag.pre(text) data = { 'plugins': plugins, 'show': req.args.get('show'), 'readonly': not os.access(get_plugins_dir(self.env), os.F_OK + os.W_OK), 'safe_wiki_to_html': safe_wiki_to_html, } return 'admin_plugins.html', data
class PluginAdminPanel(Component): implements(IAdminPanelProvider) # IAdminPanelProvider methods def get_admin_panels(self, req): if 'TRAC_ADMIN' in req.perm: yield ('general', _('General'), 'plugin', _('Plugins')) def render_admin_panel(self, req, cat, page, path_info): req.perm.require('TRAC_ADMIN') if req.method == 'POST': if 'install' in req.args: self._do_install(req) elif 'uninstall' in req.args: self._do_uninstall(req) else: self._do_update(req) anchor = '' if req.args.has_key('plugin'): anchor = '#no%d' % (int(req.args.get('plugin')) + 1) req.redirect(req.href.admin(cat, page) + anchor) return self._render_view(req) # Internal methods def _do_install(self, req): """Install a plugin.""" if not req.args.has_key('plugin_file'): raise TracError(_('No file uploaded')) upload = req.args['plugin_file'] if isinstance(upload, unicode) or not upload.filename: raise TracError(_('No file uploaded')) plugin_filename = upload.filename.replace('\\', '/').replace(':', '/') plugin_filename = os.path.basename(plugin_filename) if not plugin_filename: raise TracError(_('No file uploaded')) if not plugin_filename.endswith('.egg') and \ not plugin_filename.endswith('.py'): raise TracError( _('Uploaded file is not a Python source file or ' 'egg')) target_path = os.path.join(self.env.path, 'plugins', plugin_filename) if os.path.isfile(target_path): raise TracError( _('Plugin %(name)s already installed', name=plugin_filename)) self.log.info('Installing plugin %s', plugin_filename) flags = os.O_CREAT + os.O_WRONLY + os.O_EXCL try: flags += os.O_BINARY except AttributeError: # OS_BINARY not available on every platform pass target_file = os.fdopen(os.open(target_path, flags, 0666), 'w') try: shutil.copyfileobj(upload.file, target_file) self.log.info('Plugin %s installed to %s', plugin_filename, target_path) finally: target_file.close() # TODO: Validate that the uploaded file is actually a valid Trac plugin # Make the environment reset itself on the next request self.env.config.touch() def _do_uninstall(self, req): """Uninstall a plugin.""" plugin_filename = req.args.get('plugin_filename') if not plugin_filename: return plugin_path = os.path.join(self.env.path, 'plugins', plugin_filename) if not os.path.isfile(plugin_path): return self.log.info('Uninstalling plugin %s', plugin_filename) os.remove(plugin_path) # Make the environment reset itself on the next request self.env.config.touch() def _do_update(self, req): """Update component enablement.""" components = req.args.getlist('component') enabled = req.args.getlist('enable') added, removed = [], [] # FIXME: this needs to be more intelligent and minimize multiple # component names to prefix rules for component in components: is_enabled = bool(self.env.is_component_enabled(component)) must_enable = component in enabled if is_enabled != must_enable: self.config.set('components', component, is_enabled and 'disabled' or 'enabled') self.log.info('%sabling component %s', is_enabled and 'Dis' or 'En', component) if must_enable: added.append(component) else: removed.append(component) if added or removed: def make_list(items): parts = [item.rsplit('.', 1) for item in items] return tag.table(tag.tbody( tag.tr(tag.td(c, class_='trac-name'), tag.td('(%s.*)' % m, class_='trac-name')) for m, c in parts), class_='trac-pluglist') added.sort() removed.sort() notices = [] if removed: msg = ngettext('The following component has been disabled:', 'The following components have been disabled:', len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext('The following component has been enabled:', 'The following components have been enabled:', len(added)) notices.append(tag(msg, make_list(added))) _save_config(self.config, req, self.log, notices) def _render_view(self, req): plugins = get_plugin_info(self.env, include_core=True) def safe_wiki_to_html(context, text): try: return format_to_html(self.env, context, text) except Exception, e: self.log.error('Unable to render component documentation: %s', exception_to_unicode(e, traceback=True)) return tag.pre(text) data = { 'plugins': plugins, 'show': req.args.get('show'), 'readonly': not os.access(get_plugins_dir(self.env), os.F_OK + os.W_OK), 'safe_wiki_to_html': safe_wiki_to_html, } return 'admin_plugins.html', data