ruby-openid 2.2.3 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-openid might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +11 -0
- data/README.md +1 -2
- data/examples/rails_openid/Gemfile +41 -0
- data/examples/rails_openid/README.rdoc +261 -0
- data/examples/rails_openid/Rakefile +4 -7
- data/examples/rails_openid/app/assets/images/rails.png +0 -0
- data/examples/rails_openid/app/assets/javascripts/application.js +15 -0
- data/examples/rails_openid/app/assets/stylesheets/application.css +13 -0
- data/examples/rails_openid/app/controllers/application_controller.rb +3 -0
- data/examples/rails_openid/app/controllers/consumer_controller.rb +1 -0
- data/examples/rails_openid/app/helpers/application_helper.rb +0 -1
- data/examples/rails_openid/app/views/consumer/{index.rhtml → index.html.erb} +0 -0
- data/examples/rails_openid/app/views/layouts/{server.rhtml → server.html.erb} +4 -2
- data/examples/rails_openid/app/views/login/{index.rhtml → index.html.erb} +0 -0
- data/examples/rails_openid/app/views/server/{decide.rhtml → decide.html.erb} +1 -0
- data/examples/rails_openid/config.ru +4 -0
- data/examples/rails_openid/config/application.rb +62 -0
- data/examples/rails_openid/config/boot.rb +4 -17
- data/examples/rails_openid/config/database.yml +15 -64
- data/examples/rails_openid/config/environment.rb +4 -53
- data/examples/rails_openid/config/environments/development.rb +32 -14
- data/examples/rails_openid/config/environments/production.rb +61 -13
- data/examples/rails_openid/config/environments/test.rb +33 -15
- data/examples/rails_openid/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails_openid/config/initializers/inflections.rb +15 -0
- data/examples/rails_openid/config/initializers/mime_types.rb +5 -0
- data/examples/rails_openid/config/initializers/rails_root.rb +1 -0
- data/examples/rails_openid/config/initializers/secret_token.rb +7 -0
- data/examples/rails_openid/config/initializers/session_store.rb +8 -0
- data/examples/rails_openid/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails_openid/config/locales/en.yml +5 -0
- data/examples/rails_openid/config/routes.rb +65 -18
- data/examples/rails_openid/db/development.sqlite3 +0 -0
- data/examples/rails_openid/db/seeds.rb +7 -0
- data/examples/rails_openid/doc/README_FOR_APP +1 -1
- data/examples/rails_openid/log/development.log +2052 -0
- data/examples/rails_openid/public/404.html +23 -5
- data/examples/rails_openid/public/422.html +26 -0
- data/examples/rails_openid/public/500.html +22 -5
- data/examples/rails_openid/public/javascripts/application.js +2 -0
- data/examples/rails_openid/public/javascripts/controls.js +586 -373
- data/examples/rails_openid/public/javascripts/dragdrop.js +575 -186
- data/examples/rails_openid/public/javascripts/effects.js +763 -489
- data/examples/rails_openid/public/javascripts/prototype.js +3420 -885
- data/examples/rails_openid/public/robots.txt +5 -1
- data/examples/rails_openid/script/rails +6 -0
- data/examples/rails_openid/test/performance/browsing_test.rb +12 -0
- data/examples/rails_openid/test/test_helper.rb +7 -22
- data/lib/openid/association.rb +1 -1
- data/lib/openid/consumer/checkid_request.rb +1 -1
- data/lib/openid/consumer/discovery.rb +1 -1
- data/lib/openid/consumer/html_parse.rb +3 -1
- data/lib/openid/consumer/idres.rb +1 -1
- data/lib/openid/extensions/ax.rb +2 -3
- data/lib/openid/extensions/ui.rb +3 -3
- data/lib/openid/extras.rb +2 -2
- data/lib/openid/server.rb +2 -2
- data/lib/openid/store/memory.rb +1 -2
- data/lib/openid/store/nonce.rb +1 -1
- data/lib/openid/trustroot.rb +1 -1
- data/lib/openid/util.rb +2 -2
- data/lib/openid/version.rb +1 -1
- data/lib/openid/yadis/xrds.rb +1 -1
- data/test/test_accept.rb +20 -21
- data/test/test_association.rb +4 -8
- data/test/test_associationmanager.rb +1 -1
- data/test/test_ax.rb +0 -1
- data/test/test_checkid_request.rb +7 -8
- data/test/test_dh.rb +1 -1
- data/test/test_discover.rb +7 -8
- data/test/test_extension.rb +1 -1
- data/test/test_fetchers.rb +7 -11
- data/test/test_filters.rb +0 -4
- data/test/test_idres.rb +5 -5
- data/test/test_kvpost.rb +0 -1
- data/test/test_message.rb +10 -11
- data/test/test_parsehtml.rb +0 -1
- data/test/test_server.rb +11 -30
- data/test/test_stores.rb +2 -2
- data/test/test_trustroot.rb +1 -1
- data/test/test_urinorm.rb +1 -1
- data/test/test_xrds.rb +1 -1
- data/test/test_yadis_discovery.rb +0 -2
- metadata +34 -33
- data/examples/rails_openid/app/controllers/application.rb +0 -4
- data/examples/rails_openid/script/about +0 -3
- data/examples/rails_openid/script/breakpointer +0 -3
- data/examples/rails_openid/script/console +0 -3
- data/examples/rails_openid/script/destroy +0 -3
- data/examples/rails_openid/script/generate +0 -3
- data/examples/rails_openid/script/performance/benchmarker +0 -3
- data/examples/rails_openid/script/performance/profiler +0 -3
- data/examples/rails_openid/script/plugin +0 -3
- data/examples/rails_openid/script/process/reaper +0 -3
- data/examples/rails_openid/script/process/spawner +0 -3
- data/examples/rails_openid/script/process/spinner +0 -3
- data/examples/rails_openid/script/runner +0 -3
- data/examples/rails_openid/script/server +0 -3
@@ -1 +1,5 @@
|
|
1
|
-
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
|
1
|
+
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
|
2
|
+
#
|
3
|
+
# To ban all spiders from the entire site uncomment the next two lines:
|
4
|
+
# User-Agent: *
|
5
|
+
# Disallow: /
|
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'rails/performance_test_help'
|
3
|
+
|
4
|
+
class BrowsingTest < ActionDispatch::PerformanceTest
|
5
|
+
# Refer to the documentation for all available options
|
6
|
+
# self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
|
7
|
+
# :output => 'tmp/performance', :formats => [:flat] }
|
8
|
+
|
9
|
+
def test_homepage
|
10
|
+
get '/'
|
11
|
+
end
|
12
|
+
end
|
@@ -1,28 +1,13 @@
|
|
1
1
|
ENV["RAILS_ENV"] = "test"
|
2
|
-
require File.expand_path(
|
3
|
-
require 'test_help'
|
2
|
+
require File.expand_path('../../config/environment', __FILE__)
|
3
|
+
require 'rails/test_help'
|
4
4
|
|
5
|
-
class
|
6
|
-
#
|
7
|
-
# in a transaction that's rolled back on completion. This ensures that the
|
8
|
-
# test database remains unchanged so your fixtures don't have to be reloaded
|
9
|
-
# between every test method. Fewer database queries means faster tests.
|
5
|
+
class ActiveSupport::TestCase
|
6
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
10
7
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
# Every Active Record database supports transactions except MyISAM tables
|
15
|
-
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
16
|
-
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
17
|
-
# is recommended.
|
18
|
-
self.use_transactional_fixtures = true
|
19
|
-
|
20
|
-
# Instantiated fixtures are slow, but give you @david where otherwise you
|
21
|
-
# would need people(:david). If you don't want to migrate your existing
|
22
|
-
# test cases which use the @david style and don't mind the speed hit (each
|
23
|
-
# instantiated fixtures translates to a database query per test method),
|
24
|
-
# then set this back to true.
|
25
|
-
self.use_instantiated_fixtures = false
|
8
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
9
|
+
# -- they do not yet inherit this setting
|
10
|
+
fixtures :all
|
26
11
|
|
27
12
|
# Add more helper methods to be used by all tests here...
|
28
13
|
end
|
data/lib/openid/association.rb
CHANGED
@@ -74,7 +74,7 @@ module OpenID
|
|
74
74
|
Util.assert(data.length == FIELD_ORDER.length)
|
75
75
|
|
76
76
|
pairs = FIELD_ORDER.map{|field| [field.to_s, data[field]]}
|
77
|
-
return Util.seq_to_kv(pairs,
|
77
|
+
return Util.seq_to_kv(pairs, true)
|
78
78
|
end
|
79
79
|
|
80
80
|
# The number of seconds until this association expires
|
@@ -121,7 +121,7 @@ module OpenID
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
if @assoc
|
124
|
+
if @assoc && (message.is_openid1 || !['checkid_setup', 'checkid_immediate'].include?(mode))
|
125
125
|
message.set_arg(OPENID_NS, 'assoc_handle', @assoc.handle)
|
126
126
|
assoc_log_msg = "with assocication #{@assoc.handle}"
|
127
127
|
else
|
@@ -489,7 +489,7 @@ module OpenID
|
|
489
489
|
|
490
490
|
def self.discover(identifier)
|
491
491
|
if Yadis::XRI::identifier_scheme(identifier) == :xri
|
492
|
-
|
492
|
+
discover_xri(identifier)
|
493
493
|
else
|
494
494
|
return discover_uri(identifier)
|
495
495
|
end
|
@@ -39,7 +39,9 @@ module OpenID
|
|
39
39
|
rescue ArgumentError
|
40
40
|
begin
|
41
41
|
stripped = html.encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '').gsub(REMOVED_RE,'')
|
42
|
-
rescue Encoding::UndefinedConversionError
|
42
|
+
rescue Encoding::UndefinedConversionError, Encoding::ConverterNotFoundError
|
43
|
+
# needed for a problem in JRuby where it can't handle the conversion.
|
44
|
+
# see details here: https://github.com/jruby/jruby/issues/829
|
43
45
|
stripped = html.encode('UTF-8', 'ASCII', :invalid => :replace, :undef => :replace, :replace => '').gsub(REMOVED_RE,'')
|
44
46
|
end
|
45
47
|
end
|
data/lib/openid/extensions/ax.rb
CHANGED
@@ -275,8 +275,7 @@ module OpenID
|
|
275
275
|
def initialize
|
276
276
|
super()
|
277
277
|
@mode = nil
|
278
|
-
@data = {}
|
279
|
-
@data.default = []
|
278
|
+
@data = Hash.new { |hash, key| hash[key] = [] }
|
280
279
|
end
|
281
280
|
|
282
281
|
# Add a single value for the given attribute type to the
|
@@ -483,7 +482,7 @@ module OpenID
|
|
483
482
|
begin
|
484
483
|
obj.parse_extension_args(ax_args)
|
485
484
|
return obj
|
486
|
-
rescue Error
|
485
|
+
rescue Error
|
487
486
|
return nil
|
488
487
|
end
|
489
488
|
end
|
data/lib/openid/extensions/ui.rb
CHANGED
@@ -30,13 +30,13 @@ module OpenID
|
|
30
30
|
# checkid_* OpenID message
|
31
31
|
# return nil if the extension was not requested.
|
32
32
|
def self.from_openid_request(oid_req)
|
33
|
-
|
33
|
+
ui_req = new
|
34
34
|
args = oid_req.message.get_args(NS_URI)
|
35
35
|
if args == {}
|
36
36
|
return nil
|
37
37
|
end
|
38
|
-
|
39
|
-
return
|
38
|
+
ui_req.parse_extension_args(args)
|
39
|
+
return ui_req
|
40
40
|
end
|
41
41
|
|
42
42
|
# Set UI extension parameters
|
data/lib/openid/extras.rb
CHANGED
@@ -3,11 +3,11 @@ class String
|
|
3
3
|
other = other.to_s
|
4
4
|
head = self[0, other.length]
|
5
5
|
head == other
|
6
|
-
end
|
6
|
+
end unless ''.respond_to?(:starts_with?)
|
7
7
|
|
8
8
|
def ends_with?(other)
|
9
9
|
other = other.to_s
|
10
10
|
tail = self[-1 * other.length, other.length]
|
11
11
|
tail == other
|
12
|
-
end
|
12
|
+
end unless ''.respond_to?(:ends_with?)
|
13
13
|
end
|
data/lib/openid/server.rb
CHANGED
@@ -122,7 +122,7 @@ module OpenID
|
|
122
122
|
is_valid = signatory.verify(@assoc_handle, @signed)
|
123
123
|
# Now invalidate that assoc_handle so it this checkAuth
|
124
124
|
# message cannot be replayed.
|
125
|
-
signatory.invalidate(@assoc_handle,
|
125
|
+
signatory.invalidate(@assoc_handle, true)
|
126
126
|
response = OpenIDResponse.new(self)
|
127
127
|
valid_str = is_valid ? "true" : "false"
|
128
128
|
response.fields.set_arg(OPENID_NS, 'is_valid', valid_str)
|
@@ -322,7 +322,7 @@ module OpenID
|
|
322
322
|
session_type = message.get_arg(OPENID2_NS, 'session_type')
|
323
323
|
if !session_type
|
324
324
|
raise ProtocolError.new(message,
|
325
|
-
|
325
|
+
"session_type missing from request")
|
326
326
|
end
|
327
327
|
end
|
328
328
|
|
data/lib/openid/store/memory.rb
CHANGED
data/lib/openid/store/nonce.rb
CHANGED
@@ -37,7 +37,7 @@ module OpenID
|
|
37
37
|
def Nonce.check_timestamp(nonce_str, allowed_skew=nil, now=nil)
|
38
38
|
allowed_skew = skew if allowed_skew.nil?
|
39
39
|
begin
|
40
|
-
stamp,
|
40
|
+
stamp, _ = split_nonce(nonce_str)
|
41
41
|
rescue ArgumentError # bad timestamp
|
42
42
|
return false
|
43
43
|
end
|
data/lib/openid/trustroot.rb
CHANGED
data/lib/openid/util.rb
CHANGED
@@ -108,8 +108,8 @@ for (var i = 0; i < elements.length; i++) {
|
|
108
108
|
|
109
109
|
ESCAPE_TABLE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''' }
|
110
110
|
# Modified from ERb's html_encode
|
111
|
-
def Util.html_encode(
|
112
|
-
|
111
|
+
def Util.html_encode(str)
|
112
|
+
str.to_s.gsub(/[&<>"']/) {|s| ESCAPE_TABLE[s] }
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
data/lib/openid/version.rb
CHANGED
data/lib/openid/yadis/xrds.rb
CHANGED
data/test/test_accept.rb
CHANGED
@@ -94,7 +94,6 @@ module OpenID
|
|
94
94
|
lines = getTestData()
|
95
95
|
chunks = chunk(lines)
|
96
96
|
data_sets = chunks.collect { |chunk| parseLines(chunk) }
|
97
|
-
cases = []
|
98
97
|
data_sets.each { |data|
|
99
98
|
lnos = []
|
100
99
|
lno, header = data['accept']
|
@@ -117,7 +116,7 @@ module OpenID
|
|
117
116
|
raise
|
118
117
|
end
|
119
118
|
|
120
|
-
|
119
|
+
sprintf('MatchAcceptTest for lines %s', lnos)
|
121
120
|
|
122
121
|
# Test:
|
123
122
|
accepted = Yadis.parse_accept_header(header)
|
@@ -134,25 +133,25 @@ module OpenID
|
|
134
133
|
# for it.
|
135
134
|
|
136
135
|
# Form: [input_array, expected_header_string]
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
136
|
+
[
|
137
|
+
# Empty input list
|
138
|
+
[[], ""],
|
139
|
+
# Content type name only; no q value
|
140
|
+
[["test"], "test"],
|
141
|
+
# q = 1.0 should be omitted from the header
|
142
|
+
[[["test", 1.0]], "test"],
|
143
|
+
# Test conversion of float to string
|
144
|
+
[["test", ["with_q", 0.8]], "with_q; q=0.8, test"],
|
145
|
+
# Allow string q values, too
|
146
|
+
[["test", ["with_q_str", "0.7"]], "with_q_str; q=0.7, test"],
|
147
|
+
# Test q values out of bounds
|
148
|
+
[[["test", -1.0]], nil],
|
149
|
+
[[["test", 1.1]], nil],
|
150
|
+
# Test sorting of types by q value
|
151
|
+
[[["middle", 0.5], ["min", 0.1], "max"],
|
152
|
+
"min; q=0.1, middle; q=0.5, max"],
|
153
|
+
|
154
|
+
].each { |input, expected_header|
|
156
155
|
|
157
156
|
if expected_header.nil?
|
158
157
|
assert_raise(ArgumentError) {
|
data/test/test_association.rb
CHANGED
@@ -71,16 +71,12 @@ module OpenID
|
|
71
71
|
pairs = [['key1', 'value1'],
|
72
72
|
['key2', 'value2']]
|
73
73
|
|
74
|
-
[['HMAC-SHA256', "\xfd\xaa\xfe;\xac\xfc*\x988\xad\x05d6
|
75
|
-
|
76
|
-
"\x95x\x1c&"],
|
77
|
-
['HMAC-SHA1', "\xe0\x1bv\x04\xf1G\xc0\xbb\x7f\x9a\x8b"\
|
78
|
-
"\xe9\xbc\xee}\\\xe5\xbb7*"],
|
74
|
+
[['HMAC-SHA256', "\xfd\xaa\xfe;\xac\xfc*\x988\xad\x05d6-\xeaVy\xd5\xa5Z.<\xa9\xed\x18\x82\\$\x95x\x1c&"],
|
75
|
+
['HMAC-SHA1', "\xe0\x1bv\x04\xf1G\xc0\xbb\x7f\x9a\x8b\xe9\xbc\xee}\\\xe5\xbb7*"],
|
79
76
|
].each do |assoc_type, expected|
|
80
|
-
assoc = Association.from_expires_in(3600, "handle", 'very_secret',
|
81
|
-
assoc_type)
|
77
|
+
assoc = Association.from_expires_in(3600, "handle", 'very_secret', assoc_type)
|
82
78
|
sig = assoc.sign(pairs)
|
83
|
-
assert_equal(
|
79
|
+
assert_equal(expected.force_encoding("UTF-8"), sig.force_encoding("UTF-8"))
|
84
80
|
|
85
81
|
m = Message.new(OPENID2_NS)
|
86
82
|
pairs.each { |k, v|
|
data/test/test_ax.rb
CHANGED
@@ -93,14 +93,6 @@ module OpenID
|
|
93
93
|
assert_openid_key_absent(msg, 'assoc_handle')
|
94
94
|
end
|
95
95
|
|
96
|
-
def test_check_with_assoc_handle
|
97
|
-
msg = assert_log_matches("Generated checkid") {
|
98
|
-
@checkid_req.get_message(@realm, @return_to, immediate)
|
99
|
-
}
|
100
|
-
|
101
|
-
assert_openid_value_equal(msg, 'assoc_handle', @assoc.handle)
|
102
|
-
end
|
103
|
-
|
104
96
|
def test_add_extension_arg
|
105
97
|
@checkid_req.add_extension_arg('bag:', 'color', 'brown')
|
106
98
|
@checkid_req.add_extension_arg('bag:', 'material', 'paper')
|
@@ -206,6 +198,13 @@ module OpenID
|
|
206
198
|
assert_has_required_fields(msg)
|
207
199
|
assert_has_identifiers(msg, IDENTIFIER_SELECT, IDENTIFIER_SELECT)
|
208
200
|
end
|
201
|
+
|
202
|
+
def test_no_assoc_handle
|
203
|
+
msg = assert_log_matches("Generated checkid") {
|
204
|
+
@checkid_req.get_message(@realm, @return_to, immediate)
|
205
|
+
}
|
206
|
+
assert_openid_key_absent(msg, 'assoc_handle')
|
207
|
+
end
|
209
208
|
end
|
210
209
|
|
211
210
|
class TestCheckIDRequestOpenID1 < Test::Unit::TestCase
|
data/test/test_dh.rb
CHANGED
@@ -27,7 +27,7 @@ module OpenID
|
|
27
27
|
["\xff", "\x0f", "\xf0" ],
|
28
28
|
].each do |input1, input2, expected|
|
29
29
|
actual = DiffieHellmanExposed.strxor_for_testing(input1, input2)
|
30
|
-
assert_equal(expected, actual)
|
30
|
+
assert_equal(expected.force_encoding("UTF-8"), actual.force_encoding("UTF-8"))
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/test/test_discover.rb
CHANGED
@@ -382,9 +382,9 @@ module OpenID
|
|
382
382
|
end
|
383
383
|
|
384
384
|
def test_yadisEmpty
|
385
|
-
|
386
|
-
|
387
|
-
|
385
|
+
_discover('application/xrds+xml',
|
386
|
+
read_data_file('test_discover/yadis_0entries.xml', false),
|
387
|
+
0)
|
388
388
|
end
|
389
389
|
|
390
390
|
def test_htmlEmptyYadis
|
@@ -517,7 +517,6 @@ module OpenID
|
|
517
517
|
@fetchlog << [url, body, headers]
|
518
518
|
|
519
519
|
u = URI::parse(url)
|
520
|
-
proxy_host = u.host
|
521
520
|
xri = u.path
|
522
521
|
query = u.query
|
523
522
|
|
@@ -562,7 +561,7 @@ module OpenID
|
|
562
561
|
end
|
563
562
|
|
564
563
|
def test_xri
|
565
|
-
|
564
|
+
_, services = OpenID.discover_xri('=smoker')
|
566
565
|
|
567
566
|
_checkService(services[0],
|
568
567
|
"http://www.myopenid.com/server",
|
@@ -584,7 +583,7 @@ module OpenID
|
|
584
583
|
end
|
585
584
|
|
586
585
|
def test_xri_normalize
|
587
|
-
|
586
|
+
_, services = OpenID.discover_xri('xri://=smoker')
|
588
587
|
|
589
588
|
_checkService(services[0],
|
590
589
|
"http://www.myopenid.com/server",
|
@@ -607,7 +606,7 @@ module OpenID
|
|
607
606
|
|
608
607
|
def test_xriNoCanonicalID
|
609
608
|
silence_logging {
|
610
|
-
|
609
|
+
_, services = OpenID.discover_xri('=smoker*bad')
|
611
610
|
assert(services.empty?)
|
612
611
|
}
|
613
612
|
end
|
@@ -635,7 +634,7 @@ module OpenID
|
|
635
634
|
end
|
636
635
|
|
637
636
|
def test_xri
|
638
|
-
|
637
|
+
_, services = OpenID.discover_xri('=smoker')
|
639
638
|
assert(!services.empty?, "Expected services, got zero")
|
640
639
|
assert_equal(services[0].server_url,
|
641
640
|
"http://www.livejournal.com/openid/server.bml")
|