Class BrowserGate

java.lang.Object
com.iizix.jetty.BrowserGate

public final class BrowserGate extends Object
The Browser gate of iiziApp.html (work order CC-BROWSER-GATE). It decides whether a Browser is KNOWN not to run IIZI, and it builds the iiziAppSorry.html page that is served instead: the iiziRun app in the App Store or Google Play, or the advice to update.

Two rules, both fail-open, unknown always passes:

  • rejects(String) matches the User-Agent against a CLOSED list of discontinued Browsers that lack WebSocket with binary frames, or the ECMAScript level the client JavaScript needs (ES2020, measured in the order's report). No version number is read out of a User-Agent: every entry names a Browser whose string can never change again, so the list never needs a version bump. A missing header, or one matching nothing, passes.
  • buildSorryPage(String,AppInfo) substitutes the app's name, description and store links into the page between its comment markers, keeping the markers. Every value is HTML-escaped; the two URLs are attribute-escaped and must be https:, else their block is removed.

The client gate, an ES5 script at the top of iiziApp.html, catches what no list can by testing the capabilities in the Browser itself; the appID it needs reaches it through APP_ID_MARKER.

Author:
Christopher Mindus
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    What the sorry page shows for one application.
    static final record 
    One entry of the list: a discontinued Browser family, how its User-Agent is recognized, and an exclusion for a later engine that kept the family's tokens.
    static final class 
    The INFO line of a rejected load, throttled to one per User-Agent per interval, so that production shows how many users the sorry page reaches without a bot filling the log.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    The marker in iiziApp.html that the servlet replaces, per response, with the URL-encoded appID of the request, or with nothing when there is none: "%%APPID%%".
    static final List<BrowserGate.Entry>
    The list, CLOSED: discontinued Browsers only.
    The rejection INFO line of the server: once per User-Agent per hour, logged by the servlet where it serves the sorry page, and by any later handler that gates a load the same way.
  • Method Summary

    Modifier and Type
    Method
    Description
    static String
    Builds the sorry page for an application from the iiziAppSorry.html template.
    static String
    URL-encodes an appID for the query string of the client gate.
    static String
    Escapes text for HTML content and attribute values: &, <, >, " and '.
    rejects(String userAgent)
    The server gate: tests whether a User-Agent belongs to a Browser KNOWN not to run IIZI.
    static String
    Validates a store URL: trimmed, at most MAX_URL_LENGTH characters, an absolute https: URL with a host, and nothing a URI parser rejects, so no quote, no space, no angle bracket and no control character.
  • Field Details

    • APP_ID_MARKER

      public static final String APP_ID_MARKER
      The marker in iiziApp.html that the servlet replaces, per response, with the URL-encoded appID of the request, or with nothing when there is none: "%%APPID%%".
      See Also:
    • REJECTIONS

      public static final BrowserGate.RejectionLog REJECTIONS
      The rejection INFO line of the server: once per User-Agent per hour, logged by the servlet where it serves the sorry page, and by any later handler that gates a load the same way.
    • LIST

      public static final List<BrowserGate.Entry> LIST
      The list, CLOSED: discontinued Browsers only. The specific entries come before the general ones so that the entry reported is the most telling one: an Opera Mini User-Agent is also a Presto one, a Windows Phone 7 one is also an "MSIE" one.
  • Method Details

    • rejects

      public static BrowserGate.Entry rejects(String userAgent)
      The server gate: tests whether a User-Agent belongs to a Browser KNOWN not to run IIZI.
      Parameters:
      userAgent - The User-Agent header, null when the request carried none.
      Returns:
      The entry that matched, or null: no header, an empty one, or a Browser not in the list all pass, since unknown always passes.
    • buildSorryPage

      public static String buildSorryPage(String template, BrowserGate.AppInfo info)
      Builds the sorry page for an application from the iiziAppSorry.html template.

      Substitution is by comment marker: the text between <!--NAME-BEGIN--> and <!--NAME-END--> is replaced and the markers stay, so the result is as valid a file as the template. Every pair of a name is processed.

      • App-Name: the escaped name; the template's default text stays when there is none.
      • App-Title: the whole <title> element, in whose text the template's default name - the text of the App-Name pair - is replaced by the escaped name, so that the title carries no marker: a comment inside <title> is text there, not a comment, and document.title showed the markers (CC-FIX-PWA-FOLLOWUPS, PWA-D-3). Nothing when the template has no such pair or its text does not carry the default name.
      • App-Description: a <p class="desc"> with the escaped description, or nothing, so the block collapses.
      • iOS-Link and Android-Link: the template's own block with its href="#" replaced by the attribute-escaped URL, or nothing when the URL is absent or not https:.
      • Has-App: kept when at least one link is written, else removed.
      • No-App: kept ONLY when neither link is written.
      Parameters:
      template - The template, the contents of iiziAppSorry.html.
      info - The application's information, null for an unknown application.
      Returns:
      The page.
    • validHttpsURL

      public static String validHttpsURL(String url)
      Validates a store URL: trimmed, at most MAX_URL_LENGTH characters, an absolute https: URL with a host, and nothing a URI parser rejects, so no quote, no space, no angle bracket and no control character. A URL is typed by a customer and is not trusted.
      Parameters:
      url - The URL, null for none.
      Returns:
      The trimmed URL, or null when absent or refused.
    • escapeHTML

      public static String escapeHTML(String s)
      Escapes text for HTML content and attribute values: &, <, >, " and '.
      Parameters:
      s - The text, never null.
      Returns:
      The escaped text, the same instance when nothing needed escaping.
    • encodeAppID

      public static String encodeAppID(String appID)
      URL-encodes an appID for the query string of the client gate.
      Parameters:
      appID - The appID, null or empty for none.
      Returns:
      The encoded appID, empty for none.