Module: OpenID::Util

Defined in:
lib/openid/util.rb,
lib/openid/kvform.rb

Constant Summary collapse

BASE64_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz0123456789+/"
BASE64_RE =
Regexp.compile(
  "
\\A
([#{BASE64_CHARS}]{4})*
([#{BASE64_CHARS}]{2}==|
 [#{BASE64_CHARS}]{3}=)?
\\Z",
  Regexp::EXTENDED,
)
ESCAPE_TABLE =
{"&" => "&amp;", "<" => "&lt;", ">" => "&gt;", '"' => "&quot;", "'" => "&#039;"}
@@logger =
Logger.new(STDERR)

Class Method Summary collapse

Class Method Details

.append_args(url, args) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/openid/util.rb', line 68

def self.append_args(url, args)
  url = url.dup
  return url if args.length == 0

  args = args.sort if args.respond_to?(:each_pair)

  url << (url.include?("?") ? "&" : "?")
  url << Util.urlencode(args)
end

.auto_submit_html(form, title = "OpenID transaction in progress") ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/openid/util.rb', line 94

def self.auto_submit_html(form, title = "OpenID transaction in progress")
  "
<html>
<head>
  <title>#{title}</title>
</head>
<body onload='document.forms[0].submit();'>
#{form}
<script>
var elements = document.forms[0].elements;
for (var i = 0; i < elements.length; i++) {
  elements[i].style.display = \"none\";
}
</script>
</body>
</html>
"
end

.dict_to_kv(d) ⇒ Object



104
105
106
# File 'lib/openid/kvform.rb', line 104

def self.dict_to_kv(d)
  seq_to_kv(d.entries.sort)
end

.from_base64(s) ⇒ Object

Raises:

  • (ArgumentError)


39
40
41
42
43
44
# File 'lib/openid/util.rb', line 39

def self.from_base64(s)
  without_newlines = s.gsub(/[\r\n]+/, "")
  raise ArgumentError, "Malformed input: #{s.inspect}" unless BASE64_RE.match(without_newlines)

  without_newlines.unpack1("m")
end

.html_encode(str) ⇒ Object

Modified from ERb’s html_encode



115
116
117
# File 'lib/openid/util.rb', line 115

def self.html_encode(str)
  str.to_s.gsub(/[&<>"']/) { |s| ESCAPE_TABLE[s] }
end

.kv_to_dict(s) ⇒ Object



108
109
110
111
# File 'lib/openid/kvform.rb', line 108

def self.kv_to_dict(s)
  seq = kv_to_seq(s)
  Hash[*seq.flatten]
end

.kv_to_seq(data, strict = false) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/openid/kvform.rb', line 48

def self.kv_to_seq(data, strict = false)
  # After one parse, seq_to_kv and kv_to_seq are inverses, with no
  # warnings:
  #
  # seq = kv_to_seq(s)
  # seq_to_kv(kv_to_seq(seq)) == seq
  err = lambda { |msg|
    msg = "kv_to_seq warning: #{msg}: #{data.inspect}"
    raise KVFormError, msg if strict

    Util.log(msg)
  }

  lines = data.split("\n")
  return [] if data.empty?

  if data[-1].chr != "\n"
    err.call("Does not end in a newline")
    # We don't expect the last element of lines to be an empty
    # string because split() doesn't behave that way.
  end

  pairs = []
  line_num = 0
  lines.each do |line|
    line_num += 1

    # Ignore blank lines
    next if line.strip == ""

    pair = line.split(":", 2)
    if pair.length == 2
      k, v = pair
      k_s = k.strip
      if k_s != k
        msg = "In line #{line_num}, ignoring leading or trailing whitespace in key #{k.inspect}"
        err.call(msg)
      end

      err.call("In line #{line_num}, got empty key") if k_s.empty?

      v_s = v.strip
      if v_s != v
        msg = "In line #{line_num}, ignoring leading or trailing whitespace in value #{v.inspect}"
        err.call(msg)
      end

      pairs << [k_s, v_s]
    else
      err.call("Line #{line_num} does not contain a colon")
    end
  end

  pairs
end

.log(message) ⇒ Object

change the message below to do whatever you like for logging



90
91
92
# File 'lib/openid/util.rb', line 90

def self.log(message)
  logger.info(message)
end

.loggerObject



85
86
87
# File 'lib/openid/util.rb', line 85

def self.logger
  @@logger
end

.logger=(logger) ⇒ Object



81
82
83
# File 'lib/openid/util.rb', line 81

def self.logger=(logger)
  @@logger = logger
end

.parse_query(qs) ⇒ Object



62
63
64
65
66
# File 'lib/openid/util.rb', line 62

def self.parse_query(qs)
  query = {}
  CGI.parse(qs).each { |k, v| query[k] = v[0] }
  query
end

.seq_to_kv(seq, strict = false) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/openid/kvform.rb', line 6

def self.seq_to_kv(seq, strict = false)
  # Represent a sequence of pairs of strings as newline-terminated
  # key:value pairs. The pairs are generated in the order given.
  #
  # @param seq: The pairs
  #
  # returns a string representation of the sequence
  err = lambda { |msg|
    msg = "seq_to_kv warning: #{msg}: #{seq.inspect}"
    raise KVFormError, msg if strict

    Util.log(msg)
  }

  lines = []
  seq.each do |k, v|
    unless k.is_a?(String)
      err.call("Converting key to string: #{k.inspect}")
      k = k.to_s
    end

    raise KVFormError, "Invalid input for seq_to_kv: key contains newline: #{k.inspect}" unless k.index("\n").nil?

    raise KVFormError, "Invalid input for seq_to_kv: key contains colon: #{k.inspect}" unless k.index(":").nil?

    err.call("Key has whitespace at beginning or end: #{k.inspect}") if k.strip != k

    unless v.is_a?(String)
      err.call("Converting value to string: #{v.inspect}")
      v = v.to_s
    end

    raise KVFormError, "Invalid input for seq_to_kv: value contains newline: #{v.inspect}" unless v.index("\n").nil?

    err.call("Value has whitespace at beginning or end: #{v.inspect}") if v.strip != v

    lines << k + ":" + v + "\n"
  end

  lines.join("")
end

.to_base64(s) ⇒ Object



35
36
37
# File 'lib/openid/util.rb', line 35

def self.to_base64(s)
  [s].pack("m").delete("\n")
end

.truthy_assert(value, message = nil) ⇒ Object



29
30
31
32
33
# File 'lib/openid/util.rb', line 29

def self.truthy_assert(value, message = nil)
  return if value

  raise AssertionError, message or value
end

.urlencode(args) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/openid/util.rb', line 46

def self.urlencode(args)
  a = []
  args.each do |key, val|
    if val.nil?
      val = ""
    elsif !!val == val
      # it's boolean let's convert it to string representation
      # or else CGI::escape won't like it
      val = val.to_s
    end

    a << (CGI.escape(key) + "=" + CGI.escape(val))
  end
  a.join("&")
end