module Net::IMAP::SASL::SASLprep

SASLprep#saslprep can be used to prepare a string according to [RFC4013].

SASLprep maps characters three ways: to nothing, to space, and Unicode normalization form KC. SASLprep prohibits codepoints from nearly all standard StringPrep tables (RFC3454, Appendix “C”), and uses StringPrep’s standard bidirectional characters requirements (Appendix “D”). SASLprep also uses StringPrep’s definition of “Unassigned” codepoints (Appendix “A”).

Constants

ASCII_NO_CTRLS

Used to short-circuit strings that don’t need preparation.

BIDI_FAILURE

Bidirectional Characters [StringPrep, §6]

MAP_TO_NOTHING

RFC4013 §2.1 Mapping - mapped to nothing

the "commonly mapped to nothing" characters (\StringPrep\[\"B.1\"])
that can be mapped to nothing.

Equal to StringPrep["B.1"]. Redefined here to avoid loading the StringPrep module.

MAP_TO_SPACE

RFC4013 §2.1 Mapping - mapped to space

  • non-ASCII space characters (StringPrep["C.1.2"]) that can be mapped to SPACE (U+0020), and

Equal to StringPrep["C.1.2"]. Redefined here to avoid loading the StringPrep module.

PROHIBITED

Matches strings prohibited by RFC4013 §2.3 and §2.4.

This checks prohibited output and bidirectional characters.

PROHIBITED_OUTPUT

Matches codepoints prohibited by RFC4013 §2.3.

See TABLES_PROHIBITED.

Equal to Regexp.union of the TABLES_PROHIBITED tables. Redefined here to avoid loading the StringPrep module unless necessary.

PROHIBITED_OUTPUT_STORED

Matches codepoints prohibited by RFC4013 §2.3 and §2.5.

See TABLES_PROHIBITED_STORED.

PROHIBITED_STORED

Matches strings prohibited by RFC4013 §2.3, §2.4, and §2.5.

This checks prohibited output, bidirectional characters, and unassigned codepoints.

TABLES_PROHIBITED
RFC4013 §2.3 Prohibited Output
  • Non-ASCII space characters — StringPrep["C.1.2"]

  • ASCII control characters — StringPrep["C.2.1"]

  • Non-ASCII control characters — StringPrep["C.2.2"]

  • Private Use characters — StringPrep["C.3"]

  • Non-character code points — StringPrep["C.4"]

  • Surrogate code points — StringPrep["C.5"]

  • Inappropriate for plain text characters — StringPrep["C.6"]

  • Inappropriate for canonical representation characters — StringPrep["C.7"]

  • Change display properties or deprecated characters — StringPrep["C.8"]

  • Tagging characters — StringPrep["C.9"]

TABLES_PROHIBITED_STORED

Adds unassigned (by Unicode 3.2) codepoints to TABLES_PROHIBITED.

RFC4013 §2.5 Unassigned Code Points

This profile specifies the StringPrep["A.1"] table as its list of unassigned code points.

UNASSIGNED
RFC4013 §2.5 Unassigned Code Points

This profile specifies the StringPrep["A.1"] table as its list of unassigned code points.

Public Instance Methods

saslprep(str, stored: false, exception: false) click to toggle source

Prepares a UTF-8 string for comparison, using the SASLprep profile RFC4013 of the StringPrep algorithm RFC3454.

By default, prohibited strings will return nil. When exception is true, a StringPrepError describing the violation will be raised.

When stored is true, “unassigned” codepoints will be prohibited. For StringPrep and the SASLprep profile, “unassigned” refers to Unicode 3.2, and not later versions. See RFC3454 §7 for more information.

# File net-imap-0.3.4.1/lib/net/imap/sasl/saslprep.rb, line 31
def saslprep(str, stored: false, exception: false)
  return str if ASCII_NO_CTRLS.match?(str) # raises on incompatible encoding
  str = str.encode("UTF-8") # also dups (and raises for invalid encoding)
  str.gsub!(MAP_TO_SPACE, " ")
  str.gsub!(MAP_TO_NOTHING, "")
  str.unicode_normalize!(:nfkc)
  # These regexps combine the prohibited and bidirectional checks
  return str unless str.match?(stored ? PROHIBITED_STORED : PROHIBITED)
  return nil unless exception
  # raise helpful errors to indicate *why* it failed:
  tables = stored ? TABLES_PROHIBITED_STORED : TABLES_PROHIBITED
  StringPrep.check_prohibited! str, *tables, bidi: true, profile: "SASLprep"
  raise StringPrep::InvalidStringError.new(
    "unknown error", string: string, profile: "SASLprep"
  )
rescue ArgumentError, Encoding::CompatibilityError => ex
  if /invalid byte sequence|incompatible encoding/.match? ex.message
    return nil unless exception
    raise StringPrepError.new(ex.message, string: str, profile: "saslprep")
  end
  raise ex
end