lib/otp/uri.rb in otp-0.0.9 vs lib/otp/uri.rb in otp-0.0.10
- old
+ new
@@ -1,72 +1,48 @@
require "uri"
module OTP
module URI
+ SCHEME = "otpauth"
+
module_function
- SCHEME = "othauth"
-
def parse(uri_string)
uri = ::URI.parse(uri_string)
- raise "URI scheme not match: #{uri.scheme}" unless uri.scheme != SCHEME
- otp = otp_class(uri).new
- m = %r{/(?:([^:]*): *)?(.+)}.match(::URI.decode(uri.path))
+ if uri.scheme.downcase != SCHEME
+ raise "URI scheme not match: #{uri.scheme}"
+ end
+ otp = type_to_class(uri).new
+ unless m = %r{/(?:([^:]*): *)?(.+)}.match(::URI.decode(uri.path))
+ raise "account name must be present: #{uri_string}"
+ end
otp.issuer = m[1] if m[1]
otp.accountname = m[2]
query = Hash[::URI.decode_www_form(uri.query)]
- otp.secret = query["secret"]
- if value = query["algorithm"]
- otp.algorithm = value
- end
- if value = query["issuer"]
- otp.issuer = value
- end
- if value = query["digits"]
- otp.digits = value.to_i
- end
- otp.extract_type_specific_uri_params(query)
+ otp.extract_uri_params(query)
return otp
end
def format(otp)
raise "secret must be set" if otp.secret.nil?
raise "accountname must be set" if otp.accountname.nil?
typename = otp.class.name.split("::")[-1].downcase
- label = otp.issuer ? "#{otp.issuer}:#{otp.accountname}" : otp.accountname
- params = pickup_params(otp)
- return "otpauth://%s/%s?%s" % [
+ label = otp.accountname.dup
+ label.prepend("#{otp.issuer}:") if otp.issuer
+ return "%s://%s/%s?%s" % [
+ SCHEME,
::URI.encode(typename),
::URI.encode(label),
- ::URI.encode_www_form(params)
+ ::URI.encode_www_form(otp.uri_params)
]
end
- def otp_class(uri)
- case uri.host.upcase
- when "HOTP"
- OTP::HOTP
- when "TOTP"
- OTP::TOTP
- else
- raise "unknown OTP type: #{uri.host}"
- end
- end
-
- def pickup_params(otp)
- param_spec = [
- [:secret, nil],
- [:issuer, nil],
- [:algorithm, OTP::Base::DEFAULT_ALGORITHM],
- [:digits, OTP::Base::DEFAULT_DIGITS],
- ]
- params = param_spec.reduce({}) do |h, (name, default)|
- value = otp.send(name)
- if value && value != default
- h[name] = value
- end
- h
- end
- return params.merge(otp.type_specific_uri_params)
+ def type_to_class(uri)
+ klass = OTP.const_get(uri.host.upcase)
+ raise unless klass.is_a?(Class)
+ raise unless klass.ancestors.include?(OTP::Base)
+ return klass
+ rescue
+ raise "unknown OTP type: #{uri.host}"
end
end
end