PhishingCheckCard ( card check domain )

1. Overview

The PhishingCheckCard module implements a reusable GTKmm (GTK4) input card used to start phishing analysis inside BastionGuard. It provides a compact, card-style interface composed of an icon, title, descriptive text, URL/domain input field, action button, and inline feedback label.

The component is designed as a self-contained UI element for phishing checks: it validates user input locally, emits a typed signal when analysis should begin, and exposes helper methods for runtime customization of title, description, placeholder text, button label, URL content, and feedback state.

The module integrates with:

  • GTKmm / GTK4 – box layout, labels, entry field, button, icon widget, alignment, and style classes
  • glibmm i18n – translated labels and validation messages through _()
  • glibmm markup – safe title rendering through Glib::Markup::escape_text()
  • sigc++ signals – outward notification via signal_analyze_requested()
  • std::regex – lightweight validation for domain/URL format checks

2. Construction and Layout

2.1 Base Widget Structure

PhishingCheckCard derives from Gtk::Box and is initialized as a vertical container with spacing 8:

PhishingCheckCard::PhishingCheckCard()
    : Gtk::Box(Gtk::Orientation::VERTICAL, 8),
      btn_analyze_(_("Analyze"))

The root widget applies the CSS class:

phishing-card

It is configured with internal margins on all sides and horizontal expansion enabled.

2.2 Internal Layout Hierarchy

The visual layout is split into two main horizontal regions inside root_box_:

  • Icon area – contained in icon_box_
  • Content area – contained in content_box_

The content area stacks the following widgets vertically:

  • lbl_title_ – bold card title
  • lbl_description_ – wrapped descriptive explanation
  • action_row_ – row containing the URL entry and analyze button
  • lbl_feedback_ – inline feedback/status message

The complete assembled structure is appended to the outer widget through append(root_box_).


3. Visual Elements and Default Content

3.1 Icon Section

The card displays a search-themed symbolic icon inside icon_box_. The implementation attempts to load:

system-search-symbolic

The icon is set to pixel size 28 and styled with:

  • phishing-card-icon-wrap – wrapper styling
  • phishing-card-icon – icon-specific styling

Icon initialization is wrapped in a try/catch block so missing icon theme resources do not cause widget construction failure.

3.2 Title and Description

The default title is rendered using Pango markup:

<b>Check a domain phishing</b>

The title is left-aligned and styled with:

phishing-card-title

The default description explains BastionGuard’s heuristic phishing analysis approach, including detection of:

  • Phishing patterns
  • Redirect chains
  • Credential-harvesting forms
  • Obfuscated scripts
  • Brand impersonation signals

The description is wrapped with Pango::WrapMode::WORD_CHAR and styled through:

phishing-card-description

3.3 Action Row

The input/action row contains:

  • entry_url_ – a single-line URL/domain input field
  • btn_analyze_ – the action button used to trigger analysis

The entry field is configured with:

  • Horizontal expansion enabled
  • Default placeholder:
    https://example.com/login

  • CSS class:
    phishing-card-entry

The analyze button is initialized with the localized label Analyze and styled with:

  • suggested-action
  • phishing-card-button

3.4 Feedback Label

The feedback label is used for inline validation and runtime status messages. It is initially hidden and styled through:

phishing-card-feedback

When error feedback is requested, the additional CSS class error is applied dynamically.


4. Signals and User Interaction

4.1 Analyze Signal Exposure

The component exposes an outward signal through:

sigc::signal<void(const Glib::ustring&)>&
PhishingCheckCard::signal_analyze_requested()

This signal is emitted only after local validation succeeds, allowing parent containers such as PhishingPage to react to clean input without duplicating basic UI validation logic.

4.2 Button and Enter-Key Trigger

The card supports two equivalent user triggers for starting analysis:

  • Clicking the analyze button
  • Pressing Enter inside the URL entry field

Both actions are connected to the same handler:

PhishingCheckCard::on_analyze_clicked()

This keeps keyboard and pointer interaction behavior fully aligned.


5. Public Runtime Customization API

The widget exposes a small customization API so the card can be reused with different wording or pre-filled values.

  • set_title(text) – updates the title using bold markup with escaped text
  • set_description(text) – replaces the descriptive paragraph
  • set_placeholder(text) – changes the URL entry placeholder
  • set_button_label(text) – changes the action button label
  • get_url() – returns the current entry content
  • set_url(url) – preloads the input field with a URL/domain
  • set_feedback(text, is_error) – displays inline feedback and optionally marks it as error state
  • clear_feedback() – clears feedback text, removes error styling, and hides the label

The title setter is explicitly safe for user-provided text because it uses Glib::Markup::escape_text() before embedding content into a <b>...</b> markup wrapper.


6. Validation Logic

6.1 Empty Input Handling

When the user triggers analysis, the handler first reads the current entry value:

const auto url = entry_url_.get_text();

If the input is empty, the card does not emit the analysis signal. Instead, it shows the inline error message:

Insert a URL or domain to analyze.

6.2 URL/Domain Format Validation

Format validation is implemented by is_valid_url(), which applies a regular expression to the raw text.

The current regex accepts:

  • Optional http:// or https:// prefix
  • Domain names with one or more dotted labels
  • localhost
  • Optional port
  • Optional path

At a high level, accepted examples include values such as:

  • example.com
  • https://example.com
  • https://example.com/login
  • localhost:8080/test

If validation fails, the card displays the error message:

The URL/domain format is not valid.

6.3 Successful Validation Path

If the input is non-empty and matches the accepted format, the card sets non-error feedback:

Analysis started...

and emits the outward analysis request signal with the raw user input.


7. Feedback State Management

Inline feedback behavior is centralized in set_feedback(text, is_error).

The method performs three coordinated actions:

  • Sets the feedback label text
  • Adds or removes the error CSS class depending on the is_error flag
  • Shows or hides the label depending on whether the text is empty

This makes the feedback widget usable both for validation errors and for neutral progress messages such as analysis start confirmation.

The companion method clear_feedback() fully resets the label to a hidden, non-error state.


8. Styling and UX Considerations

  • Card-oriented composition: the widget isolates phishing input workflow into a reusable, stylable component
  • Keyboard accessibility: the entry field supports Enter-to-analyze in addition to button click
  • Immediate validation feedback: empty and malformed input are rejected locally before any external action is triggered
  • Safe title rendering: title customization escapes markup before applying bold formatting
  • Graceful icon handling: missing symbolic icons do not break widget initialization
  • Visual error separation: the feedback label distinguishes normal and error states through a dedicated CSS class
  • Loose coupling: the widget emits an analysis signal rather than embedding network or parsing logic directly