Exemple #1
0
    def render(self, rows, view, group_cells, cells, num_columns,
               show_checkboxes):
        painted_rows = []

        header_row = []
        for cell in cells:
            header_row.append(escaping.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_for_export(joined_row)
                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:
                    content = "%s" % content
                    content = escaping.strip_tags(content.replace(
                        "<br>", "\n"))

                painted_row.append(content)

            painted_rows.append(painted_row)

        html.write(json.dumps(painted_rows, indent=True))
Exemple #2
0
def _show_json(view: "View", rows: Rows) -> None:
    painted_rows = []

    header_row = []
    for cell in view.row_cells:
        header_row.append(escaping.strip_tags(cell.export_title()))
    painted_rows.append(header_row)

    for row in rows:
        painted_row = []
        for cell in view.row_cells:
            joined_row = join_row(row, cell)
            content = cell.render_for_export(joined_row)
            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:
                content = escaping.strip_tags(
                    str(content).replace("<br>", "\n"))

            painted_row.append(content)

        painted_rows.append(painted_row)

    html.write(json.dumps(painted_rows, indent=True))
Exemple #3
0
    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([
                    escaping.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([
                    escaping.strip_tags(cell_content)
                    for cell_content, _css_classes, _colspan in row_spec
                ]))
            html.write("\n")
Exemple #4
0
    def _write_csv(self, csv_separator: str) -> None:
        rows = self.rows
        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 not isinstance(
                self.rows[0], GroupHeader):
            html.write(
                csv_separator.join([
                    escaping.strip_tags(header.title) or ""
                    for header in self.headers
                ]) + "\n")

        for row in rows:
            if isinstance(row, GroupHeader):
                continue

            html.write(
                csv_separator.join(
                    [escaping.strip_tags(cell.content) for cell in row.cells]))
            html.write("\n")
Exemple #5
0
def section(title=None,
            checkbox=None,
            section_id=None,
            simple=False,
            hide=False,
            legend=True,
            css=None):
    # type: (Union[None, HTML, str], Union[None, HTML, str, Tuple[str, bool, str]], Optional[str], bool, bool, bool, Optional[str]) -> 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=escaping.strip_tags(title))
            html.write(escaping.escape_text(title))
            html.span('.' * 200, class_="dots")
            html.close_div()
        if checkbox:
            html.open_div(class_="checkbox")
            if isinstance(checkbox, (str, 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
Exemple #6
0
def _sort_rows(rows: TableRows, sort_col: int, sort_reverse: int) -> TableRows:
    # remove and remind fixed rows, add to separate list
    fixed_rows = []
    for index, row in enumerate(rows[:]):
        if row.fixed:
            rows.remove(row)
            fixed_rows.append((index, row))

    # 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(key=lambda x: utils.key_num_split(
            escaping.strip_tags(x[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, cells in fixed_rows:
            rows.insert(index, cells)

    return rows
Exemple #7
0
    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("error rendering performeter")
            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:
            url = cmk_graph_url(row, "service")
            disabled = False
        else:
            url = "javascript:void(0)"
            disabled = True

        return " ".join(classes), \
            html.render_a(content=content, href=url, title=escaping.strip_tags(title),
                          class_=["disabled" if disabled else None])
Exemple #8
0
    def _export_audit_log(self,
                          audit: List[AuditLogStore.Entry]) -> ActionResult:
        html.set_output_format("csv")

        if self._options["display"] == "daily":
            filename = "wato-auditlog-%s_%s.csv" % (render.date(
                time.time()), render.time_of_day(time.time()))
        else:
            filename = "wato-auditlog-%s_%s_days.csv" % (render.date(
                time.time()), self._options["display"][1])

        html.response.headers[
            "Content-Disposition"] = "attachment; filename=\"%s\"" % filename

        titles = [
            _('Date'),
            _('Time'),
            _('Object type'),
            _('Object'),
            _('User'),
            _('Action'),
            _('Summary'),
        ]

        if self._show_details:
            titles.append(_('Details'))

        html.write(','.join(titles) + '\n')
        for entry in audit:
            columns = [
                render.date(int(entry.time)),
                render.time_of_day(int(entry.time)),
                entry.object_ref.object_type.name if entry.object_ref else "",
                entry.object_ref.ident if entry.object_ref else "",
                entry.user_id,
                entry.action,
                '"' + escaping.strip_tags(entry.text).replace('"', "'") + '"',
            ]

            if self._show_details:
                columns.append(
                    '"' +
                    escaping.strip_tags(entry.diff_text).replace('"', "'") +
                    '"')

            html.write(','.join(columns) + '\n')
        return FinalizeRequest(code=200)
Exemple #9
0
    def _format_for_csv(self, raw_data):
        # raw_data can also be int, float, dict (labels)
        if isinstance(raw_data, dict):
            return ', '.join(
                ["%s: %s" % (key, value) for key, value in raw_data.items()])

        return escaping.strip_tags(str(raw_data)).replace('\n', '').replace(
            '"', '""')
Exemple #10
0
def log_audit(linkinfo, action, message, user_id=None):
    if config.wato_use_git:
        if isinstance(message, HTML):
            message = escaping.strip_tags(message.value)
        cmk.gui.watolib.git.add_message(message)
    # Using escape_attribute here is against our regular rule to do the escaping
    # at the last possible time: When rendering. But this here is the last
    # place where we can distinguish between HTML() encapsulated (already)
    # escaped / allowed HTML and strings to be escaped.
    message = escaping.escape_text(message).strip()
    log_entry(linkinfo, action, message, user_id)
Exemple #11
0
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.__version__, cmk_version.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") % \
                  escaping.strip_tags(escaping.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:
            eval_response = ast.literal_eval(response)
        except SyntaxError:
            raise MKAutomationException(response)
        if isinstance(eval_response, dict):
            if cmk_version.is_managed_edition(
            ) and eval_response["edition_short"] != "cme":
                raise MKUserError(
                    None,
                    _("The Check_MK Managed Services Edition can only "
                      "be connected with other sites using the CME."))
            return eval_response["login_secret"]
        return eval_response
Exemple #12
0
def log_audit(action: str,
              message: LogMessage,
              object_ref: Optional[ObjectRef] = None,
              user_id: Optional[UserId] = None,
              diff_text: Optional[str] = None) -> None:

    if config.wato_use_git:
        if isinstance(message, HTML):
            message = escaping.strip_tags(message.value)
        cmk.gui.watolib.git.add_message(message)

    _log_entry(action, message, object_ref, user_id, diff_text)
Exemple #13
0
 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("autherr",
                   escaping.strip_tags(subfolder.reason_why_may_not("read")),
                   class_=["autherr"])
         html.div('', class_="hoverarea")
Exemple #14
0
 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(escaping.strip_tags(content)))
             html.write_text(",")
         html.write_text("],")
     html.write_text("\n]\n")
Exemple #15
0
def section(title: Union[None, HTML, str] = None,
            checkbox: Union[None, HTML, str, Tuple[str, bool, str]] = None,
            section_id: Optional[str] = None,
            simple: bool = False,
            hide: bool = False,
            legend: bool = True,
            css: Optional[str] = None,
            is_show_more: bool = False,
            is_changed: bool = False,
            is_required: bool = False) -> None:
    global g_section_open
    section_close()
    html.open_tr(
        id_=section_id,
        class_=[
            css,
            "show_more_mode" if is_show_more and not is_changed else "basic"
        ],
        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=escaping.strip_tags(title))
            html.write(escaping.escape_text(title))
            html.span('.' * 200,
                      class_=["dots", "required" if is_required else None])
            html.close_div()
        if checkbox:
            html.open_div(class_="checkbox")
            if isinstance(checkbox, (str, 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
Exemple #16
0
def _show_crash_dump_message(crash: 'GUICrashReport', plain_text: bool,
                             fail_silently: bool,
                             show_crash_link: Optional[bool]) -> None:
    """Create a crash dump from a GUI exception and display a message to the user"""

    if show_crash_link is None:
        show_crash_link = config.user.may("general.see_crash_reports")

    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 show_crash_link:
        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 = makeuri(
            request,
            [
                ("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" % escaping.strip_tags(message))
        return

    if fail_silently:
        return

    html.header(title, Breadcrumb())
    html.show_error(message)
    html.footer()
Exemple #17
0
def _export_python(view: "View", rows: Rows) -> None:
    html.write_text("[\n")
    html.write(repr([cell.export_title() for cell in view.row_cells]))
    html.write_text(",\n")
    for row in rows:
        html.write_text("[")
        for cell in view.row_cells:
            joined_row = join_row(row, cell)
            content = cell.render_for_export(joined_row)

            # The aggr_treestate painters are returning a dictionary data structure (see
            # paint_aggregated_tree_state()) in case the output_format is not HTML. Only
            # remove the HTML tags from the top level strings produced by painters.
            if isinstance(content, (HTML, str)):
                content = escaping.strip_tags(content)

            html.write(repr(content))
            html.write_text(",")
        html.write_text("],")
    html.write_text("\n]\n")
Exemple #18
0
    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)
                content = cell.render_for_export(joined_row)

                # The aggr_treestate painters are returning a dictionary data structure (see
                # paint_aggregated_tree_state()) in case the output_format is not HTML. Only
                # remove the HTML tags from the top level strings produced by painters.
                if isinstance(content, (HTML, six.string_types)):
                    content = escaping.strip_tags(content)

                html.write(repr(content))
                html.write_text(",")
            html.write_text("],")
        html.write_text("\n]\n")
Exemple #19
0
 def _format_for_csv(self, raw_data):
     # raw_data can also be int, float
     content = "%s" % raw_data
     stripped = escaping.strip_tags(content).replace('\n',
                                                     '').replace('"', '""')
     return stripped.encode("utf-8")
    def _show_configuration_variables(self, groups):
        search = self._search

        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)
                    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=escaping.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("error converting %r to text", value)
                    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: Optional[str] = "modified"
                    value_title: Optional[str] = _("This option has been modified.")
                elif varname in self._global_settings:
                    modified_cls = "modified globally"
                    value_title = _("This option has been modified in global settings.")
                else:
                    modified_cls = None
                    value_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=value_title,
                    )
                    html.close_div()

                else:
                    html.a(HTML(to_text), href=edit_url, class_=modified_cls, title=value_title)

            if header_is_painted:
                forms.end()
        if not at_least_one_painted and search:
            html.show_message(_('Did not find any global setting matching your search.'))
        html.close_div()
Exemple #21
0
    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(),
                           escaping.escape_attribute(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 = escaping.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())
Exemple #22
0
 def _format_for_csv(self, raw_data):
     # raw_data can also be int, float
     return escaping.strip_tags(str(raw_data)).replace('\n', '').replace(
         '"', '""')