each_pair

in lib/gitlab/auth/ldap/dn.rb [58:195]


        def each_pair
          state = :key
          key = StringIO.new
          value = StringIO.new
          hex_buffer = ""

          @dn.each_char.with_index do |char, dn_index|
            case state
            when :key then
              case char
              when 'a'..'z', 'A'..'Z' then
                state = :key_normal
                key << char
              when '0'..'9' then
                state = :key_oid
                key << char
              when ' ' then state = :key
              else raise(MalformedError, "Unrecognized first character of an RDN attribute type name \"#{char}\"")
              end
            when :key_normal then
              case char
              when '=' then state = :value
              when 'a'..'z', 'A'..'Z', '0'..'9', '-', ' ' then key << char
              else raise(MalformedError, "Unrecognized RDN attribute type name character \"#{char}\"")
              end
            when :key_oid then
              case char
              when '=' then state = :value
              when '0'..'9', '.', ' ' then key << char
              else raise(MalformedError, "Unrecognized RDN OID attribute type name character \"#{char}\"")
              end
            when :value then
              case char
              when '\\' then state = :value_normal_escape
              when '"' then state = :value_quoted
              when ' ' then state = :value
              when '#' then
                state = :value_hexstring
                value << char
              when ',' then
                state = :key
                yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
                key = StringIO.new
                value = StringIO.new
              else
                state = :value_normal
                value << char
              end
            when :value_normal then
              case char
              when '\\' then state = :value_normal_escape
              when ',' then
                state = :key
                yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
                key = StringIO.new
                value = StringIO.new
              when '+' then raise(UnsupportedError, "Multivalued RDNs are not supported")
              else value << char
              end
            when :value_normal_escape then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_normal_escape_hex
                hex_buffer = char
              else
                state = :value_normal
                value << char
              end
            when :value_normal_escape_hex then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_normal
                value << "#{hex_buffer}#{char}".to_i(16).chr
              else raise(MalformedError, "Invalid escaped hex code \"\\#{hex_buffer}#{char}\"")
              end
            when :value_quoted then
              case char
              when '\\' then state = :value_quoted_escape
              when '"' then state = :value_end
              else value << char
              end
            when :value_quoted_escape then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_quoted_escape_hex
                hex_buffer = char
              else
                state = :value_quoted
                value << char
              end
            when :value_quoted_escape_hex then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_quoted
                value << "#{hex_buffer}#{char}".to_i(16).chr
              else raise(MalformedError, "Expected the second character of a hex pair inside a double quoted value, but got \"#{char}\"")
              end
            when :value_hexstring then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_hexstring_hex
                value << char
              when ' ' then state = :value_end
              when ',' then
                state = :key
                yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
                key = StringIO.new
                value = StringIO.new
              else raise(MalformedError, "Expected the first character of a hex pair, but got \"#{char}\"")
              end
            when :value_hexstring_hex then
              case char
              when '0'..'9', 'a'..'f', 'A'..'F' then
                state = :value_hexstring
                value << char
              else raise(MalformedError, "Expected the second character of a hex pair, but got \"#{char}\"")
              end
            when :value_end then
              case char
              when ' ' then state = :value_end
              when ',' then
                state = :key
                yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
                key = StringIO.new
                value = StringIO.new
              else raise(MalformedError, "Expected the end of an attribute value, but got \"#{char}\"")
              end
            else raise "Fell out of state machine"
            end
          end

          
          raise(MalformedError, 'DN string ended unexpectedly') unless
            [:value, :value_normal, :value_hexstring, :value_end].include? state

          yield key.string.strip, rstrip_except_escaped(value.string, @dn.length)
        end