def _sort_rows(rows, sort_col, sort_reverse): # remove and remind fixed rows, add to separate list fixed_rows = [] for index, row_spec in enumerate(rows[:]): if row_spec[3] is True: rows.remove(row_spec) fixed_rows.append((index, row_spec)) # Then use natural sorting to sort the list. Note: due to a # change in the number of columns of a table in different software # versions the cmp-function might fail. This is because the sorting # column is persisted in a user file. So we ignore exceptions during # sorting. This gives the user the chance to change the sorting and # see the table in the first place. try: rows.sort(cmp=lambda a, b: utils.cmp_num_split( html.strip_tags(a[0][sort_col][0]), html.strip_tags(b[0][sort_col][0])), reverse=sort_reverse == 1) except IndexError: pass # Now re-add the removed "fixed" rows to the list again if fixed_rows: for index, row_spec in fixed_rows: rows.insert(index, row_spec) return rows
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): painted_rows = [] header_row = [] for cell in cells: header_row.append(html.strip_tags(cell.export_title())) painted_rows.append(header_row) for row in rows: painted_row = [] for cell in cells: joined_row = join_row(row, cell) content = cell.render_content(joined_row)[1] if isinstance(content, (list, dict)): # Allow painters to return lists and dicts, then json encode them # as such data structures without wrapping them into strings pass else: if isinstance(content, six.text_type): content = content.encode("utf-8") else: content = "%s" % content content = html.strip_tags(content.replace("<br>", "\n")) painted_row.append(content) painted_rows.append(painted_row) html.write(json.dumps(painted_rows, indent=True))
def _write_csv(self, csv_separator): rows = self.rows headers = self.headers limit = self.limit omit_headers = self.options["omit_headers"] # Apply limit after search / sorting etc. if limit is not None: rows = rows[:limit] # If we have no group headers then paint the headers now if not omit_headers and self.rows and self.rows[0][2] != "header": html.write( csv_separator.join([ html.strip_tags(header) or "" for (header, _css, _help, _sortable) in headers ]) + "\n") for row_spec, _css, _state, _fixed, _attrs in rows: html.write( csv_separator.join([ html.strip_tags(cell_content) for cell_content, _css_classes, _colspan in row_spec ])) html.write("\n")
def render(self, row, cell): classes = ["perfometer"] if is_stale(row): classes.append("stale") try: title, h = Perfometer(row).render() if title is None and h is None: return "", "" except Exception as e: logger.exception() if config.debug: raise return " ".join(classes), _("Exception: %s") % e content = html.render_div(HTML(h), class_=["content"]) \ + html.render_div(title, class_=["title"]) \ + html.render_div("", class_=["glass"]) # pnpgraph_present: -1 means unknown (path not configured), 0: no, 1: yes if display_options.enabled(display_options.X) \ and row["service_pnpgraph_present"] != 0: if metrics.cmk_graphs_possible(): import cmk.gui.cee.plugins.views.graphs url = cmk.gui.cee.plugins.views.graphs.cmk_graph_url(row, "service") else: url = pnp_url(row, "service") disabled = False else: url = "javascript:void(0)" disabled = True return " ".join(classes), \ html.render_a(content=content, href=url, title=html.strip_tags(title), class_=["disabled" if disabled else None])
def do_site_login(site_id, name, password): sites = SiteManagementFactory().factory().load_sites() site = sites[site_id] if not name: raise MKUserError("_name", _("Please specify your administrator login on the remote site.")) if not password: raise MKUserError("_passwd", _("Please specify your password.")) # Trying basic auth AND form based auth to ensure the site login works. # Adding _ajaxid makes the web service fail silently with an HTTP code and # not output HTML code for an error screen. url = site["multisiteurl"] + 'login.py' post_data = { '_login': '******', '_username': name, '_password': password, '_origtarget': 'automation_login.py?_version=%s&_edition_short=%s' % (cmk.__version__, cmk.edition_short()), '_plain_error': '1', } response = get_url( url, site.get('insecure', False), auth=(name, password), data=post_data).strip() if '<html>' in response.lower(): message = _("Authentication to web service failed.<br>Message:<br>%s") % \ html.strip_tags(html.strip_scripts(response)) if config.debug: message += "<br>" + _("Automation URL:") + " <tt>%s</tt><br>" % url raise MKAutomationException(message) elif not response: raise MKAutomationException(_("Empty response from web service")) else: try: return ast.literal_eval(response) except SyntaxError: raise MKAutomationException(response)
def _show_subfolder_hoverarea(self, subfolder): # Only make folder openable when permitted to edit if subfolder.may("read"): html.open_div(class_="hoverarea", onmouseover="cmk.wato.toggle_folder(event, this, true);", onmouseout="cmk.wato.toggle_folder(event, this, false);") self._show_subfolder_buttons(subfolder) html.close_div() # hoverarea else: html.icon(html.strip_tags(subfolder.reason_why_may_not("read")), "autherr", class_=["autherr"]) html.div('', class_="hoverarea")
def render(self, rows, view, group_cells, cells, num_columns, show_checkboxes): html.write_text("[\n") html.write(repr([cell.export_title() for cell in cells])) html.write_text(",\n") for row in rows: html.write_text("[") for cell in cells: joined_row = join_row(row, cell) _tdclass, content = cell.render_content(joined_row) html.write(repr(html.strip_tags(content))) html.write_text(",") html.write_text("],") html.write_text("\n]\n")
def section(title=None, checkbox=None, section_id=None, simple=False, hide=False, legend=True, css=None): global g_section_open if g_section_open: html.close_td() html.close_tr() html.open_tr(id_=section_id, class_=[css], style="display:none;" if hide else None) if legend: html.open_td(class_=["legend", "simple" if simple else None]) if title: html.open_div( class_=["title", "withcheckbox" if checkbox else None], title=html.strip_tags(title)) html.write(html.permissive_attrencode(title)) html.span('.' * 100, class_="dots") html.close_div() if checkbox: html.open_div(class_="checkbox") if isinstance(checkbox, six.string_types + (HTML, )): html.write(checkbox) else: name, active, attrname = checkbox html.checkbox( name, active, onclick='cmk.wato.toggle_attribute(this, \'%s\')' % attrname) html.close_div() html.close_td() html.open_td(class_=["content", "simple" if simple else None]) g_section_open = True
def show_crash_dump_message(crash, plain_text, fail_silently): # type: (GUICrashReport, bool, bool) -> None """Create a crash dump from a GUI exception and display a message to the user""" title = _("Internal error") message = u"%s: %s<br>\n<br>\n" % (title, crash.crash_info["exc_value"]) # Do not reveal crash context information to unauthenticated users or not permitted # users to prevent disclosure of internal information if not config.user.may("general.see_crash_reports"): message += _( "An internal error occurred while processing your request. " "You can report this issue to your Checkmk administrator. " "Detailed information can be found on the crash report page " "or in <tt>var/log/web.log</tt>.") else: crash_url = html.makeuri( [ ("site", config.omd_site()), ("crash_id", crash.ident_to_text()), ], filename="crash.py", ) message += _( "An internal error occured while processing your request. " "You can report this issue to the Checkmk team to help " "fixing this issue. Please open the <a href=\"%s\">crash report page</a> " "and use the form for reporting the problem.") % crash_url if plain_text: html.set_output_format("text") html.write("%s\n" % html.strip_tags(message)) return if fail_silently: return html.header(title) html.show_error(message) html.footer()
def log_audit(linkinfo, action, message, user_id=None): if config.wato_use_git: if isinstance(message, HTML): message = html.strip_tags(message.value) cmk.gui.watolib.git.add_message(message) log_entry(linkinfo, action, message, user_id)
def _show_host_row(self, rendered_hosts, table, hostname, search_text, show_checkboxes, colspan, host_errors, contact_group_names): if search_text and (search_text.lower() not in hostname.lower()): return host = self._folder.host(hostname) rendered_hosts.append(hostname) effective = host.effective_attributes() table.row() # Column with actions (buttons) if show_checkboxes: table.cell(html.render_input( "_toggle_group", type_="button", class_="checkgroup", onclick="cmk.selection.toggle_all_rows();", value='X'), sortable=False, css="checkbox") # Use CSS class "failed" in order to provide information about # selective toggling inventory-failed hosts for Javascript html.input(name="_c_%s" % hostname, type_="checkbox", value=colspan, class_="failed" if host.discovery_failed() else None) html.label("", "_c_%s" % hostname) table.cell(_("Actions"), css="buttons", sortable=False) self._show_host_actions(host) # Hostname with link to details page (edit host) table.cell(_("Hostname")) errors = host_errors.get(hostname, []) + host.validation_errors() if errors: msg = _("Warning: This host has an invalid configuration: ") msg += ", ".join(errors) html.icon(msg, "validation_error") html.nbsp() if host.is_offline(): html.icon(_("This host is disabled"), "disabled") html.nbsp() if host.is_cluster(): html.icon( _("This host is a cluster of %s") % ", ".join(host.cluster_nodes()), "cluster") html.nbsp() html.a(hostname, href=host.edit_url()) # Show attributes for attr in host_attribute_registry.attributes(): if attr.show_in_table(): attrname = attr.name() if attrname in host.attributes(): tdclass, tdcontent = attr.paint( host.attributes()[attrname], hostname) else: tdclass, tdcontent = attr.paint(effective.get(attrname), hostname) tdclass += " inherited" table.cell(attr.title(), html.attrencode(tdcontent), css=tdclass) # Am I authorized? reason = host.reason_why_may_not("read") if not reason: icon = "authok" title = _("You have permission to this host.") else: icon = "autherr" title = html.strip_tags(reason) table.cell(_('Auth'), html.render_icon(icon, title), css="buttons", sortable=False) # Permissions and Contact groups - through complete recursion and inhertance permitted_groups, host_contact_groups, _use_for_services = host.groups( ) table.cell( _("Permissions"), HTML(", ").join([ self._render_contact_group(contact_group_names, g) for g in permitted_groups ])) table.cell( _("Contact Groups"), HTML(", ").join([ self._render_contact_group(contact_group_names, g) for g in host_contact_groups ])) if not config.wato_hide_hosttags: table.cell(_("Tags"), css="tag-ellipsis") tag_groups, show_all_code = self._limit_labels(host.tag_groups()) html.write( cmk.gui.view_utils.render_tag_groups(tag_groups, "host", with_links=False)) html.write(show_all_code) table.cell(_("Explicit labels"), css="tag-ellipsis") labels, show_all_code = self._limit_labels(host.labels()) html.write( cmk.gui.view_utils.render_labels( labels, "host", with_links=False, label_sources={k: "explicit" for k in labels.keys()})) html.write(show_all_code) # Located in folder if self._folder.is_search_folder(): table.cell(_("Folder")) html.a(host.folder().alias_path(), href=host.folder().url())
def _format_for_csv(self, raw_data): # raw_data can also be int, float content = "%s" % raw_data stripped = html.strip_tags(content).replace('\n', '').replace('"', '""') return stripped.encode("utf-8")
def _show_configuration_variables(self, groups): search_form(_("Search for settings:")) search = self._search html.open_div(class_="filter_buttons") if self._show_only_modified: html.buttonlink(html.makeuri([], delvars=["show_only_modified"]), _("Show all settings")) else: html.buttonlink(html.makeuri([("show_only_modified", "1")]), _("Show only modified settings")) html.close_div() at_least_one_painted = False html.open_div(class_="globalvars") for group in sorted(groups, key=lambda g: g.sort_index()): header_is_painted = False # needed for omitting empty groups for config_variable_class in group.config_variables(): config_variable = config_variable_class() varname = config_variable.ident() valuespec = config_variable.valuespec() if not config_variable.domain().enabled(): continue if config_variable.domain( ) == watolib.ConfigDomainCore and varname not in self._default_values: if config.debug: raise MKGeneralException( "The configuration variable <tt>%s</tt> is unknown to " "your local Check_MK installation" % varname) else: continue if not config_variable.in_global_settings(): continue if self._show_only_modified and varname not in self._current_settings: continue help_text = valuespec.help() or '' title_text = valuespec.title() if search and search not in group.title().lower() \ and search not in config_variable.domain().ident.lower() \ and search not in varname \ and search not in help_text.lower() \ and search not in title_text.lower(): continue # skip variable when search is performed and nothing matches at_least_one_painted = True if not header_is_painted: # always open headers when searching forms.header(group.title(), isopen=search or self._show_only_modified) header_is_painted = True default_value = self._default_values[varname] edit_url = watolib.folder_preserving_link([ ("mode", self._edit_mode()), ("varname", varname), ("site", html.request.var("site", "")) ]) title = html.render_a(title_text, href=edit_url, class_="modified" if varname in self._current_settings else None, title=html.strip_tags(help_text)) if varname in self._current_settings: value = self._current_settings[varname] elif varname in self._global_settings: value = self._global_settings[varname] else: value = default_value try: to_text = valuespec.value_to_text(value) except Exception: logger.exception() to_text = html.render_error( _("Failed to render value: %r") % value) # Is this a simple (single) value or not? change styling in these cases... simple = True if '\n' in to_text or '<td>' in to_text: simple = False forms.section(title, simple=simple) if varname in self._current_settings: modified_cls = "modified" title = _("This option has been modified.") elif varname in self._global_settings: modified_cls = "modified globally" title = _( "This option has been modified in global settings.") else: modified_cls = None title = None if is_a_checkbox(valuespec): html.open_div( class_=["toggle_switch_container", modified_cls]) html.toggle_switch( enabled=value, help_txt=_("Immediately toggle this setting"), href=html.makeactionuri([("_action", "toggle"), ("_varname", varname)]), class_=modified_cls, title=title, ) html.close_div() else: html.a(HTML(to_text), href=edit_url, class_=modified_cls, title=title) if header_is_painted: forms.end() if not at_least_one_painted and search: html.message( _('Did not find any global setting matching your search.')) html.close_div()