# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true module Contrast module Utils # Utilities for encoding and normalizing strings class StringUtils UTF8 = 'utf-8' HTTP_PREFIX = 'HTTP-' # Convenience method. We assume that we're working on Strings or tags # String representations of things. To that end, we'll to_s anything # that comes in before returning its length. # # But don't worry though, String.to_s just returns self. teehee def self.ret_length string string.nil? ? 0 : string.to_s.length end # Protobuf has a very strict typing. Nil is not a String and will throw # an exception if you try to set it. Use this to be safe. # Uses the object share to avoid creating several new strings per request def self.protobuf_safe_string string string.nil? ? Contrast::Utils::ObjectShare::EMPTY_STRING : string.to_s end # Truncate a string to 255 characters max length def self.truncate str, default = Contrast::Utils::ObjectShare::EMPTY_STRING return default if str.nil? str.to_s[0..255] end def self.force_utf8 str, logger = nil return Contrast::Utils::ObjectShare::EMPTY_STRING unless str str = str.to_s if str.encoding == Encoding::UTF_8 str = str.encode(UTF8, invalid: :replace, undef: :replace) unless str.valid_encoding? else str = str.encode(UTF8, str.encoding, invalid: :replace, undef: :replace) end str.to_s rescue StandardError => e # We were unable to switch the String to a UTF-8 format. # Return non-nil so as not to throw an exception later when trying # to do regexp or other compares on the String logger&.debug "Unable to change '#{ str }' to valid UTF-8: #{ e.message }" Contrast::Utils::ObjectShare::EMPTY_STRING end # Given a string return a normalized version of that string. # Keys are memoized so that the normalization process doesn't need # to happen every time. def self.normalized_key str return nil unless str str = str.to_s @_normalized_keys ||= {} if @_normalized_keys.key?(str) @_normalized_keys[str] else up = str.upcase.strip up = up.gsub(/[_-]/, '-') up = up[5..-1] if up.start_with?(HTTP_PREFIX) @_normalized_keys[str] = up end end end end end