# Class PiiScrubber

java.lang.Object
com.codename1.crash.PiiScrubber

public class PiiScrubber extends Object

Default PII scrubber for `CrashProtection` uploads. Designed to be subclassed: override `scrubMessage(String)` or `scrubFrame(String, String)` to extend the behaviour, then register the subclass with `CrashProtection.setScrubber(PiiScrubber)`.

Default behaviour applied to exception message strings only:

1. Emails partially redacted: the local part is truncated to its first three characters followed by `***`, the domain is preserved. Example: `johndoe@example.com` becomes `joh***@example.com`.
2. Runs of six or more consecutive digits are replaced with `[num]`, catching phone numbers, long IDs, etc.
3. URLs are NOT scrubbed (they routinely carry useful debugging context; if a particular app embeds tokens in URLs it can opt-in to URL scrubbing by overriding this class).

Stack frames are not scrubbed by default. Class and method names do not carry PII; subclasses that emit synthetic frames containing user data may override `scrubFrame(String, String)`.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `PiiScrubber()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected static String`
  `scrubDigitRuns(String s)`
  Replaces every run of six or more consecutive ASCII digits with the literal token `[num]`.
  `protected static String`
  `scrubEmails(String s)`
  Replaces all occurrences of an email-like substring with the form `<first-three>***@<domain>`.
  `String`
  `scrubFrame(String className, String methodName)`
  Scrubs PII from a single stack frame.
  `String`
  `scrubMessage(String message)`
  Scrubs PII from a free-form message, typically an exception message.
  `String`
  `scrubRawStack(String rawStack)`
  Scrubs a pre-rendered stack string.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### PiiScrubber

    public PiiScrubber()

- ## Method Details

  - ### scrubMessage

    public String scrubMessage(String message)

    Scrubs PII from a free-form message, typically an exception message. The default implementation applies email partial redaction and long-digit-run masking.

    ###### Parameters

    - `message`: original message; may be `null`.

    ###### Returns

    scrubbed message, or `null` if `message` is `null`.

  - ### scrubFrame

    public String scrubFrame(String className, String methodName)

    Scrubs PII from a single stack frame. Default implementation returns the original method name unchanged.

    ###### Parameters

    - `className`: fully-qualified class name of the frame.
    - `methodName`: method name of the frame.

    ###### Returns

    the (possibly modified) method name to upload.

  - ### scrubRawStack

    public String scrubRawStack(String rawStack)

    Scrubs a pre-rendered stack string. On the ParparVM ports the whole Java trace arrives as one string rather than structured frames, and on the JavaScript port it is the engine's `Error().stack`. A stricter application can override this to redact aggressively.

    The default scrubs emails everywhere and applies long-digit-run masking UNIFORMLY to every line, frame-shaped or not. It does not try to preserve a frame's line/column: `printStackTrace` writes the exception message verbatim, and a message can embed an indented, frame-shaped line that is indistinguishable from a real frame -- preserving a "coordinate" from such a line would let a crafted `:line:column` tail smuggle a long id past the digit masking. `scrubMessage` masks only 6-or-more-digit runs, so ordinary short line numbers survive, but a large minified-JavaScript column such as `app.js:1:123456` is masked to `app.js:1:[num]`. That loses the column for this text form; precise coordinates for symbolication come from the structured frames (real `StackTraceElement`s), not this scrubbed string.

    ###### Parameters

    - `rawStack`: the pre-rendered stack string; may be `null`.

    ###### Returns

    the scrubbed stack string, or `null` if `rawStack` is `null`.

    EVERY line is routed through `scrubMessage(String)` -- the overridable method -- so an app that redacts app-specific tokens there redacts them in `rawStack` too. No line is treated as a "frame" whose coordinate is preserved: `printStackTrace` writes the exception MESSAGE verbatim, and a message can contain an embedded, indented, frame-shaped line (e.g. code that folds another stack trace into a message), which is indistinguishable from a real frame by any shape or indentation check. Preserving a "coordinate" from such a line would let a crafted `:line:column` tail bypass digit masking. So the raw stack is scrubbed uniformly; `scrubMessage` masks only 6+ digit runs, so ordinary short line numbers survive and stay readable, while a large minified-bundle column (or a long id planted as a fake column) is masked. Precise coordinates for symbolication come from the structured frames, which are real `StackTraceElement`s, not parsed text. The app's `scrubFrame(String, String)` override is still applied to a `at <class>.<method>` line so a synthetic method name redacted from the structured frames does not resurface here.

  - ### scrubEmails

    protected static String scrubEmails(String s)

    Replaces all occurrences of an email-like substring with the form `<first-three>***@<domain>`. Local parts shorter than three characters are not padded; the original prefix is preserved and followed by `***`. The domain (including TLD) is preserved verbatim.

    This implementation is character-driven rather than regex-based to stay compatible with the Java 5 source level enforced by the core framework module.

  - ### scrubDigitRuns

    protected static String scrubDigitRuns(String s)
    Replaces every run of six or more consecutive ASCII digits with the literal token `[num]`.