1 2 3 4 5 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 47 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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
module OpenID
class KVFormError < Exception
end
module Util
def Util.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}"
if strict
raise KVFormError, msg
else
Util.log(msg)
end
}
lines = []
seq.each { |k, v|
if !k.is_a?(String)
err.call("Converting key to string: #{k.inspect}")
k = k.to_s
end
if !k.index("\n").nil?
raise KVFormError, "Invalid input for seq_to_kv: key contains newline: #{k.inspect}"
end
if !k.index(":").nil?
raise KVFormError, "Invalid input for seq_to_kv: key contains colon: #{k.inspect}"
end
if k.strip() != k
err.call("Key has whitespace at beginning or end: #{k.inspect}")
end
if !v.is_a?(String)
err.call("Converting value to string: #{v.inspect}")
v = v.to_s
end
if !v.index("\n").nil?
raise KVFormError, "Invalid input for seq_to_kv: value contains newline: #{v.inspect}"
end
if v.strip() != v
err.call("Value has whitespace at beginning or end: #{v.inspect}")
end
lines << k + ":" + v + "\n"
}
return lines.join("")
end
def Util.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}"
if strict
raise KVFormError, msg
else
Util.log(msg)
end
}
lines = data.split("\n")
if data.length == 0
return []
end
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 { |line|
line_num += 1
# Ignore blank lines
if line.strip() == ""
next
end
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
if k_s.length == 0
err.call("In line #{line_num}, got empty key")
end
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
}
return pairs
end
def Util.dict_to_kv(d)
return seq_to_kv(d.entries.sort)
end
def Util.kv_to_dict(s)
seq = kv_to_seq(s)
return Hash[*seq.flatten]
end
end
end
|