def show(self, breadcrumb: Breadcrumb) -> None: html.open_div(class_="breadcrumb") for item in breadcrumb: if item.url: html.a(escape_to_html(str(item.title)), href=item.url) else: html.span(escape_to_html(str(item.title))) html.close_div()
def show(self) -> None: html.open_table(cellspacing="0", class_="sitestate") sites.update_site_states_from_dead_sites() for sitename, _sitealias in user_sites.sorted_sites(): site = site_config.get_site_config(sitename) state = sites.states().get(sitename, sites.SiteStatus({})).get("state") if state is None: state = "missing" switch = "missing" text = escape_to_html(sitename) else: if state == "disabled": switch = "on" text = escape_to_html(site["alias"]) else: switch = "off" text = render_link( site["alias"], "view.py?view_name=sitehosts&site=%s" % sitename) html.open_tr() html.td(text, class_="left") html.open_td(class_="state") if switch == "missing": html.status_label(content=state, status=state, title=_("Site is missing")) else: url = makeactionuri_contextless( request, transactions, [ ("_site_switch", "%s:%s" % (sitename, switch)), ], filename="switch_site.py", ) html.status_label_button( content=state, status=state, title=_("enable this site") if state == "disabled" else _("disable this site"), onclick="cmk.sidebar.switch_site(%s)" % (json.dumps(url)), ) html.close_tr() html.close_table()
def action(self) -> ActionResult: if request.var("_reset"): if not transactions.check_transaction(): return None try: del self._current_settings[self._varname] except KeyError: pass msg = escape_to_html( _("Resetted configuration variable %s to its default.") % self._varname) else: new_value = self._valuespec.from_html_vars("ve") self._valuespec.validate_value(new_value, "ve") self._current_settings[self._varname] = new_value msg = HTML( _("Changed global configuration variable %s to %s.") % ( escaping.escape_attribute(self._varname), self._valuespec.value_to_html(new_value), )) self._save() _changes.add_change( "edit-configvar", msg, sites=self._affected_sites(), domains=[self._config_variable.domain()], need_restart=self._config_variable.need_restart(), ) return redirect(self._back_url())
def _warn_about_local_files(self, crash_info: CrashInfo) -> None: if crash_info["crash_type"] == "check": files = [] for filepath, _lineno, _func, _line in crash_info["exc_traceback"]: if "/local/" in filepath: files.append(filepath) if files: warn_text = escaping.escape_to_html( _("The following files located in the local hierarchy of your site are involved in this exception:" )) warn_text += HTMLWriter.render_ul( HTML("\n").join(map(HTMLWriter.render_li, files))) warn_text += escaping.escape_to_html( _("Maybe these files are not compatible with your current Checkmk " "version. Please verify and only report this crash when you think " "this should be working.")) html.show_warning(warn_text)
def insert_manpage_links(text: str) -> HTML: parts = text.replace(",", " ").split() new_parts: List[HTML] = [] check_regex = re.compile(r"[-_\.a-z0-9]") for part in parts: if check_regex.match(part) and os.path.exists( cmk.utils.paths.check_manpages_dir + "/" + part): url = makeuri_contextless( request, [ ("mode", "check_manpage"), ("check_type", part), ], filename="wato.py", ) new_parts.append(html.render_a(content=part, href=url)) else: new_parts.append(escape_to_html(part)) return HTML(" ").join(new_parts)
def parse_file(site, host_name, file_name, hidecontext=False): log_chunks: List[Dict[str, Any]] = [] try: chunk: Optional[Dict[str, Any]] = None lines = get_logfile_lines(site, host_name, file_name) if lines is None: return None # skip hash line. this doesn't exist in older files while lines and lines[0].startswith("#"): lines = lines[1:] for line in lines: line = line.strip() if line == "": continue if line[:3] == "<<<": # new chunk begins log_lines: List[Dict[str, Any]] = [] chunk = {"lines": log_lines} log_chunks.append(chunk) # New header line date, logtime, level = line[3:-3].split(" ") # Save level as integer to make it better comparable if level == "CRIT": chunk["level"] = 2 elif level == "WARN": chunk["level"] = 1 elif level == "OK": chunk["level"] = 0 else: chunk["level"] = 0 # Gather datetime object # Python versions below 2.5 don't provide datetime.datetime.strptime. # Use the following instead: # chunk['datetime'] = datetime.datetime.strptime(date + ' ' + logtime, "%Y-%m-%d %H:%M:%S") chunk["datetime"] = datetime.datetime( *time.strptime(date + " " + logtime, "%Y-%m-%d %H:%M:%S")[0:5]) elif chunk: # else: not in a chunk?! # Data line line_display = line[2:] # Classify the line for styling if line[0] == "W": line_level = 1 line_class = "WARN" elif line[0] == "u": line_level = 1 line_class = "WARN" elif line[0] == "C": line_level = 2 line_class = "CRIT" elif line[0] == "O": line_level = 0 line_class = "OK" elif not hidecontext: line_level = 0 line_class = "context" else: continue # ignore this line log_lines.append({ "level": line_level, "class": line_class, "line": line_display }) except Exception as e: if config.debug: raise raise MKGeneralException( escape_to_html(_("Cannot parse log file %s: %s") % (file_name, e))) return log_chunks
def _process_icon( what: IconObjectType, row: Row, tags: List[TagID], custom_vars: Dict[str, str], icon_id: str, icon: Icon, ) -> Iterator[ABCIconEntry]: # In old versions, the icons produced html code directly. The new API # is that the icon functions need to return: # a) None - nothing to be rendered # b) single string - the icon name (without .png) # c) tuple - icon, title # d) triple - icon, title, url result: Union[None, str, HTML, Tuple[str, str], Tuple[str, str, str]] try: result = icon.render(what, row, tags, custom_vars) except Exception: if active_config.debug: raise yield IconEntry( sort_index=icon.sort_index(), icon_name="alert", title=_("Exception in icon '%s': %s") % (icon_id, traceback.format_exc()), ) if result is None: return title, url = None, None icon_name: str = "" if isinstance(result, (str, HTML)): # TODO: This is handling the deprecated API with 1.2.7. Remove this one day. But there # are icons that still use this API. These need to be cleaned up before. # LM: There are icons that still use this API if (isinstance(result, str) and result[0] == "<") or ( isinstance(result, HTML) and str(result)[0] == "<" ): # seems like an old format icon (html code). In regular rendering # case (html), it can simply be appended to the output. Otherwise # extract the icon name from icon images if html.output_format == "html": if isinstance(result, str): result = escape_to_html(result) yield LegacyIconEntry(sort_index=icon.sort_index(), code=result) else: # Strip icon names out of HTML code that is generated by htmllib.render_icon() for n in cmk.utils.regex.regex('<img src="([^"]*)"[^>]*>').findall(str(result)): if n.startswith("images/"): n = n[7:] if n.startswith("icon_"): n = n[5:] if n.endswith(".png"): n = n[:-4] yield IconEntry(sort_index=icon.sort_index(), icon_name=n) return assert isinstance(result, str) icon_name = result else: # Mypy does not understand the length checking here. Can not easily be fixed, because we # would have to change all the icon plugins. if len(result) == 2: icon_name, title = result # type: ignore[misc] elif len(result) == 3: icon_name, title, url = result # type: ignore[misc] else: raise NotImplementedError() yield IconEntry( sort_index=icon.sort_index(), icon_name=icon_name, title=title, url_spec=url, )
def title(self): if self._search: return _("Global settings matching '%s'") % escape_to_html( self._search) return _("Global settings")
def _show_patterns(self): import cmk.gui.logwatch as logwatch collection = watolib.SingleRulesetRecursively("logwatch_rules") collection.load() ruleset = collection.get("logwatch_rules") html.h3(_("Logfile patterns")) if ruleset.is_empty(): html.open_div(class_="info") html.write_text( "There are no logfile patterns defined. You may create " 'logfile patterns using the <a href="%s">Rule Editor</a>.' % watolib.folder_preserving_link( [ ("mode", "edit_ruleset"), ("varname", "logwatch_rules"), ] ) ) html.close_div() # Loop all rules for this ruleset already_matched = False abs_rulenr = 0 for folder, rulenr, rule in ruleset.get_rules(): # Check if this rule applies to the given host/service if self._hostname: service_desc = self._get_service_description(self._hostname, "logwatch", self._item) # If hostname (and maybe filename) try match it rule_matches = rule.matches_host_and_item( watolib.Folder.current(), self._hostname, self._item, service_desc ) else: # If no host/file given match all rules rule_matches = True with foldable_container( treename="rule", id_=str(abs_rulenr), isopen=True, title=HTML("<b>Rule #%d</b>" % (abs_rulenr + 1)), indent=False, ), table_element( "pattern_editor_rule_%d" % abs_rulenr, sortable=False, css="logwatch" ) as table: abs_rulenr += 1 # TODO: What's this? pattern_list = rule.value if isinstance(pattern_list, dict): pattern_list = pattern_list["reclassify_patterns"] # Each rule can hold no, one or several patterns. Loop them all here for state, pattern, comment in pattern_list: match_class = "" disp_match_txt = HTML("") match_img = "" if rule_matches: # Applies to the given host/service matched = re.search(pattern, self._match_txt) if matched: # Prepare highlighted search txt match_start = matched.start() match_end = matched.end() disp_match_txt = ( escape_to_html(self._match_txt[:match_start]) + html.render_span( self._match_txt[match_start:match_end], class_="match" ) + escape_to_html(self._match_txt[match_end:]) ) if not already_matched: # First match match_class = "match first" match_img = "match" match_title = _( "This logfile pattern matches first and will be used for " "defining the state of the given line." ) already_matched = True else: # subsequent match match_class = "match" match_img = "imatch" match_title = _( "This logfile pattern matches but another matched first." ) else: match_img = "nmatch" match_title = _("This logfile pattern does not match the given string.") else: # rule does not match match_img = "nmatch" match_title = _("The rule conditions do not match.") table.row() table.cell(_("Match")) html.icon("rule%s" % match_img, match_title) cls: List[str] = [] if match_class == "match first": cls = ["state%d" % logwatch.level_state(state), "fillbackground"] table.cell(_("State"), html.render_span(logwatch.level_name(state)), css=cls) table.cell(_("Pattern"), html.render_tt(pattern)) table.cell(_("Comment"), comment) table.cell(_("Matched line"), disp_match_txt) table.row(fixed=True) table.cell(colspan=5) edit_url = watolib.folder_preserving_link( [ ("mode", "edit_rule"), ("varname", "logwatch_rules"), ("rulenr", rulenr), ("item", watolib.mk_repr(self._item).decode()), ("rule_folder", folder.path()), ("rule_id", rule.id), ] ) html.icon_button(edit_url, _("Edit this rule"), "edit")
def mk_eval(s: Union[bytes, str]) -> Any: try: return ast.literal_eval(base64.b64decode(s).decode()) except Exception: raise MKGeneralException( _("Unable to parse provided data: %s") % escape_to_html(repr(s)))
def _show_login_page(self) -> None: html.set_render_headfoot(False) html.add_body_css_class("login") html.header(get_page_heading(), Breadcrumb(), javascripts=[]) default_origtarget = ("index.py" if requested_file_name(request) in ["login", "logout"] else makeuri(request, [])) origtarget = request.get_url_input("_origtarget", default_origtarget) # Never allow the login page to be opened in the iframe. Redirect top page to login page. # This will result in a full screen login page. html.javascript("""if(top != self) { window.top.location.href = location; }""") # When someone calls the login page directly and is already authed redirect to main page if requested_file_name(request) == "login" and _check_auth(request): raise HTTPRedirect(origtarget) html.open_div(id_="login") html.open_div(id_="login_window") html.open_a(href="https://checkmk.com") html.img( src=theme.detect_icon_path(icon_name="logo", prefix="mk-"), id_="logo", class_="custom" if theme.has_custom_logo() else None, ) html.close_a() html.begin_form("login", method="POST", add_transid=False, action="login.py") html.hidden_field("_login", "1") html.hidden_field("_origtarget", origtarget) html.label("%s:" % _("Username"), id_="label_user", class_=["legend"], for_="_username") html.br() html.text_input("_username", id_="input_user") html.label("%s:" % _("Password"), id_="label_pass", class_=["legend"], for_="_password") html.br() html.password_input("_password", id_="input_pass", size=None) if user_errors: html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.open_div(id_="button_text") html.button("_login", _("Login"), cssclass="hot") html.close_div() html.close_div() html.open_div(id_="foot") if config.login_screen.get("login_message"): html.open_div(id_="login_message") html.show_message(config.login_screen["login_message"]) html.close_div() footer: List[HTML] = [] for title, url, target in config.login_screen.get("footer_links", []): footer.append(html.render_a(title, href=url, target=target)) if "hide_version" not in config.login_screen: footer.append( escape_to_html("Version: %s" % cmk_version.__version__)) footer.append( HTML("© %s" % html.render_a( "tribe29 GmbH", href="https://tribe29.com", target="_blank"))) html.write_html(HTML(" - ").join(footer)) if cmk_version.is_raw_edition(): html.br() html.br() html.write_text( _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">' "GNU GPL Version 2</a>.") % "https://checkmk.com/gpl.html") html.close_div() html.set_focus("_username") html.hidden_fields() html.end_form() html.close_div() html.footer()
def _process_message_message(msg): msg["id"] = utils.gen_id() msg["time"] = time.time() if isinstance(msg["dest"], str): dest_what = msg["dest"] else: dest_what = msg["dest"][0] if dest_what == "all_users": recipients = list(active_config.multisite_users.keys()) elif dest_what == "online": recipients = userdb.get_online_user_ids() elif dest_what == "list": recipients = msg["dest"][1] else: recipients = [] num_recipients = len(recipients) num_success: Dict[str, int] = {} for method in msg["methods"]: num_success[method] = 0 # Now loop all messaging methods to send the messages errors: Dict[str, List[Tuple]] = {} for user_id in recipients: for method in msg["methods"]: try: handler = _messaging_methods()[method]["handler"] handler(user_id, msg) num_success[method] = num_success[method] + 1 except MKInternalError as e: errors.setdefault(method, []).append((user_id, e)) message = escape_to_html(_("The message has successfully been sent...")) message += html.render_br() parts = [] for method in msg["methods"]: parts.append( html.render_li( _messaging_methods()[method]["confirmation_title"] + ( _(" for all recipients.") if num_success[method] == num_recipients else _(" for %d of %d recipients.") % (num_success[method], num_recipients) ) ) ) message += html.render_ul(HTML().join(parts)) message += html.render_p(_("Recipients: %s") % ", ".join(recipients)) html.show_message(message) if errors: error_message = HTML() for method, method_errors in errors.items(): error_message += _("Failed to send %s messages to the following users:") % method table_rows = HTML() for user_id, exception in method_errors: table_rows += html.render_tr( html.render_td(html.render_tt(user_id)) + html.render_td(str(exception)) ) error_message += html.render_table(table_rows) + html.render_br() html.show_error(error_message)
def test_escape_to_html() -> None: assert isinstance(escaping.escape_to_html(""), HTML) assert str(escaping.escape_to_html("")) == "" assert str(escaping.escape_to_html("<script>")) == "<script>" assert str(escaping.escape_to_html("<b>")) == "<b>"