class Analyzer::Mobile::Ios

Overview

Parses iOS configuration files to surface mobile app entry points:

Same model as the Android analyzer: one endpoint per URI, method "GET", mobile semantics in protocol. iOS declares no handler in the config (deep links are dispatched by the App/SceneDelegate onOpenURL / application(_:open:)), so via is filled later by the code layer.

Defined in:

analyzer/analyzers/mobile/ios.cr

Constant Summary

BUILD_VAR_RE = /\$[({]([A-Za-z_][A-Za-z0-9_]*)[)}]/

$(VAR) / ${VAR} build-setting reference.

BUILD_VAR_REF_RE = Regex.union("$(", "${")

Presence-only gate for the same reference syntax. One precompiled Regex.union scan (PCRE2 JIT) replaces the OR-ed String#includes?("$(") / String#includes?("${") pair used to short-circuit substitution/resolution below.

ENUM_CASE_LINE_RE = /^\s*case\s+(.+)$/
ENUM_CASE_NAME_RE = /^([A-Za-z_][A-Za-z0-9_]*)\s*(?:=\s*"([^"]*)")?$/
GENERIC_SCHEMES = Set {"http", "https", "file", "content"}

Generic web/file schemes an app may register without them being a real deep-link surface (a bare http:// / https:// has no host to address). Compared case-insensitively.

HOST_ENUM_SITE_RE = /\.(?:host|scheme)\S*\s*[=!]?=\s*([A-Z][A-Za-z0-9_]*)\.[A-Za-z_][A-Za-z0-9_]*\.rawValue|([A-Z][A-Za-z0-9_]*)\.[A-Za-z_][A-Za-z0-9_]*\.rawValue\s*[=!]?=\s*\S*\.(?:host|scheme)|\[[^\]\n]*\b([A-Z][A-Za-z0-9_]*)\.[A-Za-z_][A-Za-z0-9_]*\.rawValue[^\]\n]*\]\s*\.contains\(\s*\S*\.(?:host|scheme)/

.host/.scheme connected to EnumName.case.rawValue via a comparison (==/!=), an assignment (=), or membership in a [...].contains(...) array literal — the shapes real routers use to test/set a scheme's host against a String-backed enum. Deliberately not a full expression parser: forms that separate the two sides further (e.g. url.host ?? "" == ...) are missed in exchange for not firing on two unrelated statements that merely share a line (a bare .host/.scheme substring next to an unrelated capitalized-enum .rawValue reference elsewhere on the same line).

MAX_BUILD_VAR_EXPANSIONS = 32
MAX_BUILD_VAR_SUBSTITUTION_DEPTH = 8
MAX_BUILD_VAR_VALUES_PER_KEY = 16
MAX_CASES_PER_ENUM = 200
MAX_HOST_ENUMS = 20
MAX_LITERAL_ROUTES = 500
MAX_PBXPROJ_FILES = 10
MAX_XCCONFIG_FILES = 40
PBXPROJ_ASSIGN_RE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([^;]*)\s*;\s*$/

KEY = value; (project.pbxproj build setting assignment).

URL_DOMAIN_SERVICES = {"applinks:", "appclips:"}

Associated-domain service prefixes that designate a URL entry point.

  • applinks — a tapped https:// URL opens the full app (universal link)
  • appclips — a tapped https:// URL launches the App Clip; same URL mechanism, but a distinct (often less-trusted, friction- reduced) surface that the App Clip target handles via NSUserActivity. App Clip targets ship their own *.entitlements that frequently list domains the main app does NOT (e.g. pocket-casts appclips:pocketcasts.net), so skipping them dropped a real entry point. webcredentials / activitycontinuation are autofill/handoff plumbing, not URL entry points, and stay ignored.
XCCONFIG_ASSIGN_RE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([^\n]*)$/

KEY = value (xcconfig assignment); the value runs to a trailing comment / end of line.

XCCONFIG_SEARCH_DEPTH = 6

How far up from the Info.plist to look for the project's build settings files, and how many to read.

Class Method Summary

Instance Method Summary

Instance methods inherited from class Analyzer

analyze analyze, base_path : String base_path, base_paths : Array(String) base_paths, base_relative_path(path : String) : String base_relative_path, callees_needed? : Bool callees_needed?, content_matches?(content : String, markers : Regex) : Bool content_matches?, http_header_name(name : String) : String | Nil http_header_name, line_number_for_index(content : String, char_index : Int32) : Int32 line_number_for_index, logger : NoirLogger logger, parallel_analyze(files : Array(String), &block : String -> Nil) parallel_analyze, read_file_content(path : String) : String read_file_content, result : Array(Endpoint) result, unique_params(params : Array(Param)) : Array(Param) unique_params, url : String url, web_root_path(path : String, markers : Array(String)) : String web_root_path

Constructor methods inherited from class Analyzer

new(options : Hash(String, YAML::Any)) new

Macros inherited from class Analyzer

analyzer_for(tech) analyzer_for

Instance methods inherited from module FileHelper

all_files : Array(String) all_files, get_files_by_basename(basename : String) : Array(String) get_files_by_basename, get_files_by_extension(extension : String) : Array(String) get_files_by_extension, get_files_by_extensions(extensions : Array(String)) : Array(String) get_files_by_extensions, get_files_by_prefix(prefix : String) : Array(String) get_files_by_prefix, get_files_by_prefix_and_extension(prefix : String, extension : String) : Array(String) get_files_by_prefix_and_extension, get_files_by_relative_path(relative_path : String, root : String = "") : Array(String) get_files_by_relative_path, get_public_dir_files(base_path : String, folder : String) : Array(String) get_public_dir_files, get_public_files(base_path : String, anchors : Array(String) = ["shard.yml", "Gemfile"]) : Array(String) get_public_files, walked_path(expanded : String) : String walked_path

Class Method Detail

def self.tech_name : String #

[View source]

Instance Method Detail

def analyze #

[View source]